1
0
mirror of https://github.com/0rangebananaspy/authelia.git synced 2024-09-14 22:47:21 +07:00
authelia/src/server/lib/LdapClient.ts
2017-06-16 18:16:38 +02:00

170 lines
5.1 KiB
TypeScript

import util = require("util");
import BluebirdPromise = require("bluebird");
import exceptions = require("./Exceptions");
import Dovehash = require("dovehash");
import ldapjs = require("ldapjs");
import { EventEmitter } from "events";
import { LdapConfiguration } from "./../../types/Configuration";
import { Ldapjs } from "../../types/Dependencies";
import { Winston } from "../../types/Dependencies";
interface SearchEntry {
object: any;
}
export class LdapClient {
private options: LdapConfiguration;
private ldapjs: Ldapjs;
private logger: Winston;
private client: ldapjs.ClientAsync;
constructor(options: LdapConfiguration, ldapjs: Ldapjs, logger: Winston) {
this.options = options;
this.ldapjs = ldapjs;
this.logger = logger;
this.connect();
}
connect(): void {
const ldap_client = this.ldapjs.createClient({
url: this.options.url,
reconnect: true
});
ldap_client.on("error", function (err: Error) {
console.error("LDAP Error:", err.message);
});
this.client = BluebirdPromise.promisifyAll(ldap_client) as ldapjs.ClientAsync;
}
private build_user_dn(username: string): string {
let user_name_attr = this.options.user_name_attribute;
// if not provided, default to cn
if (!user_name_attr) user_name_attr = "cn";
const additional_user_dn = this.options.additional_user_dn;
const base_dn = this.options.base_dn;
let user_dn = util.format("%s=%s", user_name_attr, username);
if (additional_user_dn) user_dn += util.format(",%s", additional_user_dn);
user_dn += util.format(",%s", base_dn);
return user_dn;
}
bind(username: string, password: string): BluebirdPromise<void> {
const user_dn = this.build_user_dn(username);
this.logger.debug("LDAP: Bind user %s", user_dn);
return this.client.bindAsync(user_dn, password)
.error(function (err: Error) {
throw new exceptions.LdapBindError(err.message);
});
}
private search_in_ldap(base: string, query: ldapjs.SearchOptions): BluebirdPromise<any> {
this.logger.debug("LDAP: Search for %s in %s", JSON.stringify(query), base);
return new BluebirdPromise((resolve, reject) => {
this.client.searchAsync(base, query)
.then(function (res: EventEmitter) {
const doc: SearchEntry[] = [];
res.on("searchEntry", function (entry: SearchEntry) {
doc.push(entry.object);
});
res.on("error", function (err: Error) {
reject(new exceptions.LdapSearchError(err.message));
});
res.on("end", function () {
resolve(doc);
});
})
.catch(function (err: Error) {
reject(new exceptions.LdapSearchError(err.message));
});
});
}
get_groups(username: string): BluebirdPromise<string[]> {
const user_dn = this.build_user_dn(username);
let group_name_attr = this.options.group_name_attribute;
if (!group_name_attr) group_name_attr = "cn";
const additional_group_dn = this.options.additional_group_dn;
const base_dn = this.options.base_dn;
let group_dn = base_dn;
if (additional_group_dn)
group_dn = util.format("%s,", additional_group_dn) + group_dn;
const query = {
scope: "sub",
attributes: [group_name_attr],
filter: "member=" + user_dn
};
const that = this;
this.logger.debug("LDAP: get groups of user %s", username);
return this.search_in_ldap(group_dn, query)
.then(function (docs) {
const groups = [];
for (let i = 0; i < docs.length; ++i) {
groups.push(docs[i].cn);
}
that.logger.debug("LDAP: got groups %s", groups);
return BluebirdPromise.resolve(groups);
});
}
get_emails(username: string): BluebirdPromise<string[]> {
const that = this;
const user_dn = this.build_user_dn(username);
const query = {
scope: "base",
sizeLimit: 1,
attributes: ["mail"]
};
this.logger.debug("LDAP: get emails of user %s", username);
return this.search_in_ldap(user_dn, query)
.then(function (docs) {
const emails = [];
for (let i = 0; i < docs.length; ++i) {
if (typeof docs[i].mail === "string")
emails.push(docs[i].mail);
else {
emails.concat(docs[i].mail);
}
}
that.logger.debug("LDAP: got emails %s", emails);
return BluebirdPromise.resolve(emails);
});
}
update_password(username: string, new_password: string): BluebirdPromise<void> {
const user_dn = this.build_user_dn(username);
const encoded_password = Dovehash.encode("SSHA", new_password);
const change = {
operation: "replace",
modification: {
userPassword: encoded_password
}
};
const that = this;
this.logger.debug("LDAP: update password of user %s", username);
this.logger.debug("LDAP: bind admin");
return this.client.bindAsync(this.options.user, this.options.password)
.then(function () {
that.logger.debug("LDAP: modify password");
return that.client.modifyAsync(user_dn, change);
});
}
}