UNPKG

@raddiamond/nexauth-core

Version:

Core authentication plugin supporting Local, AD authentication

111 lines (110 loc) 4.72 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var __param = (this && this.__param) || function (paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); } }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ADIdentityProvider = void 0; const ldapjs_1 = __importDefault(require("ldapjs")); const tsyringe_1 = require("tsyringe"); let ADIdentityProvider = class ADIdentityProvider { constructor(context) { this.context = context; this.client = ldapjs_1.default.createClient({ url: this.context.adConfig.url, reconnect: true, timeout: 5000, }); console.log('[AD] Created LDAP client for:', this.context.adConfig.url); } bindAsService() { return new Promise((resolve, reject) => { const { bindDN, bindCredentials } = this.context.adConfig; console.log('[AD] Binding as service account:', bindDN); this.client.bind(bindDN, bindCredentials, (err) => { if (err) { console.error('[AD] Service bind failed:', err.message); reject(err); } else { console.log('[AD] Service bind successful'); resolve(); } }); }); } async getUser(username) { const ad = this.context.adConfig; const userLookup = ad.userLookup; const matchAttr = userLookup.matchField; const additionalAttrs = userLookup.additionalAttributes ?? []; const searchOpts = { scope: 'sub', filter: `(${String(matchAttr)}=${String(username)})`, attributes: ['dn', String(matchAttr), 'cn', 'mail', 'displayName', 'objectGUID', ...additionalAttrs], }; try { await this.bindAsService(); return new Promise((resolve) => { let foundDN = null; let identity; this.client.search(ad.baseDN, searchOpts, (err, res) => { if (err) { console.error('[AD] Search error:', err.message); return resolve(null); } res.on('searchEntry', (entry) => { const raw = entry.attributes.reduce((acc, attr) => { acc[attr.type] = attr.values?.[0] || null; return acc; }, {}); identity = raw; foundDN = entry.dn.toString(); }); res.on('end', async () => { if (!foundDN) { return resolve(null); } identity._dn = foundDN; resolve(identity); }); }); }); } catch (err) { console.error('[AD] Failed during user lookup:', err); return null; } } async validatePassword(user, password) { if (!user || !user['_dn']) return false; const ad = this.context.adConfig; return new Promise((resolve) => { const loginClient = ldapjs_1.default.createClient({ url: ad.url }); loginClient.bind(user['_dn'], password, (err) => { if (err) { return resolve(false); } resolve(true); }); }); } }; exports.ADIdentityProvider = ADIdentityProvider; exports.ADIdentityProvider = ADIdentityProvider = __decorate([ (0, tsyringe_1.injectable)(), __param(0, (0, tsyringe_1.inject)('TenantContext')), __metadata("design:paramtypes", [Object]) ], ADIdentityProvider);