mirror of
https://github.com/0rangebananaspy/authelia.git
synced 2024-09-14 22:47:21 +07:00
170 lines
5.1 KiB
TypeScript
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);
|
|
});
|
|
}
|
|
}
|