@immobiliarelabs/backstage-plugin-ldap-auth-backend
Version:
Backstage LDAP Authentication plugin, this packages adds backend authentication and token generation/validation/management; sibling of @immobiliarelabs/backstage-plugin-ldap-auth
139 lines (135 loc) • 4.83 kB
JavaScript
;
var errors = require('@backstage/errors');
var auth = require('./auth.cjs.js');
var errors$1 = require('./errors.cjs.js');
var jwt = require('./jwt.cjs.js');
var ldap$1 = require('./ldap.cjs.js');
class ProviderLdapAuthProvider {
checkUserExists;
ldapAuthentication;
authHandler;
signInResolver;
resolverContext;
jwtValidator;
ldapAuthenticationOptions;
cookies;
constructor(options) {
this.authHandler = options.authHandler;
this.signInResolver = options.signInResolver;
this.checkUserExists = options.checkUserExists;
this.ldapAuthentication = options.ldapAuthentication;
this.resolverContext = options.resolverContext;
this.ldapAuthenticationOptions = options.ldapAuthenticationOptions;
this.cookies = options.cookies;
this.jwtValidator = options.tokenValidator || new jwt.TokenValidatorNoop();
if (Array.isArray(this.ldapAuthenticationOptions?.ldapOpts?.url)) {
this.ldapAuthenticationOptions.ldapOpts.url = this.ldapAuthenticationOptions.ldapOpts.url[0];
}
}
// must keep this methods for the interface
async start() {
return;
}
async frameHandler() {
return;
}
async check(uid) {
const exists = await this.checkUserExists({
...this.ldapAuthenticationOptions,
username: uid
});
if (!exists) throw new errors.AuthenticationError(errors$1.JWT_INVALID_TOKEN);
}
async refresh(req, res) {
try {
if (req.method !== "POST") {
throw new errors.AuthenticationError("Method not allowed");
}
const { username, password } = req.body;
const ctx = this.resolverContext;
const token = req.cookies?.[this.cookies.field];
let result;
if (username && password) {
const { uid } = await this.ldapAuthentication(
username,
password,
this.ldapAuthenticationOptions
);
result = { uid };
} else if (token) {
await this.jwtValidator.isValid(token);
const { sub } = jwt.parseJwtPayload(token);
const uid = sub.split(":").at(-1)?.split("/").at(-1);
await this.check(uid);
result = { uid };
} else {
throw new errors.AuthenticationError(errors$1.AUTH_MISSING_CREDENTIALS);
}
const { profile } = await this.authHandler(
{ uid: result.uid },
ctx
);
const backstageIdentity = await this.signInResolver(
{ profile, result },
ctx
);
const response = {
providerInfo: {},
profile,
// this backstage user information from the token and formats
// the reponse in way that's usable by the FE
backstageIdentity: auth.prepareBackstageIdentityResponse(backstageIdentity)
};
const { exp } = jwt.parseJwtPayload(backstageIdentity.token);
const maxAge = Math.ceil(
new Date(exp * 1e3).valueOf() - Date.now() + (this.jwtValidator?.increaseTokenExpireMs || 0)
);
res.cookie(this.cookies.field, backstageIdentity.token, {
maxAge,
httpOnly: true,
secure: this.cookies.secure
});
res.json(response);
} catch (e) {
res.clearCookie(this.cookies.field);
throw e;
}
}
async logout(req, res) {
const token = req.cookies?.[this.cookies.field];
await this.jwtValidator.isValid(token);
this.jwtValidator.logout(token, jwt.normalizeTime(Date.now()));
res.clearCookie(this.cookies.field);
res.status(200).end();
}
}
const ldap = {
create(options) {
return ({ config, resolverContext }) => {
const cnf = config.get(
process.env.NODE_ENV || "development"
);
cnf.cookies = {
field: cnf?.cookies?.field || jwt.COOKIE_FIELD_KEY,
secure: cnf?.cookies?.secure || false
};
const authHandler = typeof options?.authHandler === "function" ? options?.authHandler : auth.defaultAuthHandler;
const signInResolver = typeof options?.signIn?.resolver === "function" ? options?.signIn?.resolver : auth.defaultSigninResolver;
const ldapAuthentication = typeof options?.resolvers?.ldapAuthentication === "function" ? options?.resolvers?.ldapAuthentication : ldap$1.defaultLDAPAuthentication;
const checkUserExists = typeof options?.resolvers?.checkUserExists === "function" ? options?.resolvers?.checkUserExists : ldap$1.defaultCheckUserExists;
return new ProviderLdapAuthProvider({
ldapAuthenticationOptions: cnf.ldapAuthenticationOptions,
cookies: cnf.cookies,
authHandler,
signInResolver,
checkUserExists,
ldapAuthentication,
resolverContext,
tokenValidator: options.tokenValidator
});
};
}
};
exports.ProviderLdapAuthProvider = ProviderLdapAuthProvider;
exports.ldap = ldap;
//# sourceMappingURL=provider.cjs.js.map