UNPKG

@mvx/identity

Version:

identity is oidc for mvc, type-mvc is base on koa. Decorator, Ioc, AOP mvc framework on server.

1,585 lines (1,417 loc) 113 kB
'use strict'; function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } var tslib = _interopDefault(require('tslib')); var mvc = _interopDefault(require('@mvx/mvc')); var ioc = _interopDefault(require('@tsdi/ioc')); var koaSession = _interopDefault(require('koa-session')); var components = _interopDefault(require('@tsdi/components')); var url = _interopDefault(require('url')); var jsonwebtoken = _interopDefault(require('jsonwebtoken')); var http = _interopDefault(require('http')); var boot = _interopDefault(require('@tsdi/boot')); var https = _interopDefault(require('https')); var querystring = _interopDefault(require('querystring')); var crypto = _interopDefault(require('crypto')); var webfinger = _interopDefault(require('webfinger')); var request = _interopDefault(require('request')); var aop = _interopDefault(require('@tsdi/aop')); var core = _interopDefault(require('@tsdi/core')); function unwrapExports (x) { return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; } function createCommonjsModule(fn, module) { return module = { exports: {} }, fn(module, module.exports), module.exports; } var NoOpenIDError_1 = createCommonjsModule(function (module, exports) { Object.defineProperty(exports, "__esModule", { value: true }); exports.NoOpenIDError = void 0; class NoOpenIDError extends mvc.HttpError { constructor(message, response) { super(400, message); this.response = response; } static ρAnn() { return { "name": "NoOpenIDError" }; } } exports.NoOpenIDError = NoOpenIDError; }); unwrapExports(NoOpenIDError_1); var NoOpenIDError_2 = NoOpenIDError_1.NoOpenIDError; var AuthenticationError_1 = createCommonjsModule(function (module, exports) { Object.defineProperty(exports, "__esModule", { value: true }); exports.AuthenticationError = void 0; /** * error. * * @export * @class OIDCError * @extends {HttpError} */ class AuthenticationError extends mvc.HttpError { // tslint:disable-next-line: variable-name constructor(status, message, error_description) { super(status, message); this.error_description = error_description; this.name = ioc.lang.getClassName(this); this.error = this.message; this.expose = status < 500; } static ρAnn() { return { "name": "AuthenticationError" }; } } exports.AuthenticationError = AuthenticationError; }); unwrapExports(AuthenticationError_1); var AuthenticationError_2 = AuthenticationError_1.AuthenticationError; var OIDCError_1 = createCommonjsModule(function (module, exports) { Object.defineProperty(exports, "__esModule", { value: true }); exports.OIDCError = void 0; /** * error. * * @export * @class OIDCError * @extends {HttpError} */ class OIDCError extends AuthenticationError_1.AuthenticationError { constructor(message, code, uri, status) { super(status, message); this.code = code; this.uri = uri; if (!status) { switch (code) { case 'access_denied': status = 403; break; case 'server_error': status = 502; break; case 'temporarily_unavailable': status = 503; break; } } this.expose = status < 500; } static ρAnn() { return { "name": "OIDCError" }; } } exports.OIDCError = OIDCError; }); unwrapExports(OIDCError_1); var OIDCError_2 = OIDCError_1.OIDCError; var InvalidToken_1 = createCommonjsModule(function (module, exports) { Object.defineProperty(exports, "__esModule", { value: true }); exports.InvalidToken = void 0; /** * invalid token. * * @export * @class InvalidToken * @extends {AuthenticationError} */ class InvalidToken extends AuthenticationError_1.AuthenticationError { constructor(detail) { super(401, 'invalid_token', 'invalid token provided'); this.error_detail = detail; } static ρAnn() { return { "name": "InvalidToken" }; } } exports.InvalidToken = InvalidToken; }); unwrapExports(InvalidToken_1); var InvalidToken_2 = InvalidToken_1.InvalidToken; var InvalidRequest_1 = createCommonjsModule(function (module, exports) { Object.defineProperty(exports, "__esModule", { value: true }); exports.InvalidRequest = void 0; /** * invaild request error. * * @export * @class InvalidRequest * @extends {HttpError} */ class InvalidRequest extends AuthenticationError_1.AuthenticationError { constructor(description, status = 400) { super(status, '', description || 'request is invalid'); } static ρAnn() { return { "name": "InvalidRequest" }; } } exports.InvalidRequest = InvalidRequest; }); unwrapExports(InvalidRequest_1); var InvalidRequest_2 = InvalidRequest_1.InvalidRequest; var InternalOAuthError_1 = createCommonjsModule(function (module, exports) { Object.defineProperty(exports, "__esModule", { value: true }); exports.InternalOAuthError = void 0; /** * internal oauth error. * * @export * @class InternalOAuthError * @extends {AuthenticationError} */ class InternalOAuthError extends AuthenticationError_1.AuthenticationError { constructor(message, oauthError) { super(400, message); this.oauthError = oauthError; } static ρAnn() { return { "name": "InternalOAuthError" }; } } exports.InternalOAuthError = InternalOAuthError; }); unwrapExports(InternalOAuthError_1); var InternalOAuthError_2 = InternalOAuthError_1.InternalOAuthError; var errors = createCommonjsModule(function (module, exports) { Object.defineProperty(exports, "__esModule", { value: true }); tslib.__exportStar(NoOpenIDError_1, exports); tslib.__exportStar(AuthenticationError_1, exports); tslib.__exportStar(OIDCError_1, exports); tslib.__exportStar(InvalidToken_1, exports); tslib.__exportStar(InvalidRequest_1, exports); tslib.__exportStar(InternalOAuthError_1, exports); }); unwrapExports(errors); var SessionMiddleware_1 = createCommonjsModule(function (module, exports) { Object.defineProperty(exports, "__esModule", { value: true }); exports.SessionMiddleware = exports.SessionStorage = void 0; /** * Session storage. */ let SessionStorage = class SessionStorage { constructor() { } static ρAnn() { return { "name": "SessionStorage", "params": { "get": ["key", "maxAge", "data"], "set": ["key", "sess", "maxAge", "data"], "destroy": ["key"] } }; } }; SessionStorage = tslib.__decorate([ ioc.Abstract(), tslib.__metadata("design:paramtypes", []) ], SessionStorage); exports.SessionStorage = SessionStorage; /** * session middleware. * * @export * @class SessionMiddleware * @extends {MvcMiddleware} */ let SessionMiddleware = class SessionMiddleware extends mvc.MvcMiddleware { constructor() { super(...arguments); this.hasInit = false; } getMiddleware(context, koa) { if (!this.hasInit && !this.middleware) { let sessCfg = context.getConfiguration().session || {}; this.hasInit = true; this.sessCfg = Object.assign(sessCfg, { key: 'typemvc:sess', /** (number || 'session') maxAge in ms (default is 1 days) */ /** 'session' will result in a cookie that expires when session/browser is closed */ /** Warning: If a session cookie is stolen, this cookie will never expire */ maxAge: 36000000, overwrite: true, httpOnly: true, signed: true, rolling: false /** (boolean) Force a session identifier cookie to be set on every response. The expiration is reset to the original maxAge, resetting the expiration countdown. default is false **/ }, sessCfg); if (!this.sessCfg.store) { let storage = context.getContainer().getService(SessionStorage); if (storage) { this.sessCfg.store = storage; } } this.middleware = koaSession(this.sessCfg, koa); } return this.middleware; } async execute(ctx, next) { var _a; let middleware = this.getMiddleware(ctx.mvcContext, ctx.app); let error; try { return await middleware(ctx, async () => { try { await next(); } catch (err) { error = err; throw err; } }); } catch (err) { if (err === error) { throw err; } else { (_a = ctx.mvcContext.getLogManager().getLogger()) === null || _a === void 0 ? void 0 : _a.error(err); } } } static ρAnn() { return { "name": "SessionMiddleware", "params": { "getMiddleware": ["context", "koa"], "execute": ["ctx", "next"] } }; } }; SessionMiddleware = tslib.__decorate([ mvc.Middleware({ name: mvc.MiddlewareTypes.Session, before: mvc.MiddlewareTypes.Cors }) ], SessionMiddleware); exports.SessionMiddleware = SessionMiddleware; }); unwrapExports(SessionMiddleware_1); var SessionMiddleware_2 = SessionMiddleware_1.SessionMiddleware; var SessionMiddleware_3 = SessionMiddleware_1.SessionStorage; var IAuthenticator = createCommonjsModule(function (module, exports) { Object.defineProperty(exports, "__esModule", { value: true }); exports.AuthenticatorToken = void 0; /** * IAuthenticator token. */ exports.AuthenticatorToken = new ioc.InjectToken('Authenticator'); }); unwrapExports(IAuthenticator); var IAuthenticator_1 = IAuthenticator.AuthenticatorToken; var IStrategy = createCommonjsModule(function (module, exports) { Object.defineProperty(exports, "__esModule", { value: true }); }); unwrapExports(IStrategy); var ValidationResult_1 = createCommonjsModule(function (module, exports) { Object.defineProperty(exports, "__esModule", { value: true }); exports.ValidationResult = void 0; /** * auth action * * @export * @class AuthAction */ class ValidationResult { constructor() { } static ρAnn() { return { "name": "ValidationResult" }; } } exports.ValidationResult = ValidationResult; }); unwrapExports(ValidationResult_1); var ValidationResult_2 = ValidationResult_1.ValidationResult; var FailResult_1 = createCommonjsModule(function (module, exports) { Object.defineProperty(exports, "__esModule", { value: true }); exports.FailResult = void 0; /** * Fail authentication, with optional `challenge` and `status`, defaulting * to 401. * * Strategies should return this action to fail an authentication attempt. * * @param {String} challenge * @param {Number} status * @api public */ class FailResult extends ValidationResult_1.ValidationResult { constructor(challenge, status) { super(); this.challenge = challenge; this.status = status; } action(ctx) { ctx.failures.push({ challenge: this.challenge, status: this.status }); } static ρAnn() { return { "name": "FailResult" }; } } exports.FailResult = FailResult; }); unwrapExports(FailResult_1); var FailResult_2 = FailResult_1.FailResult; var PassResult_1 = createCommonjsModule(function (module, exports) { Object.defineProperty(exports, "__esModule", { value: true }); exports.PassResult = void 0; /** * Pass without making a success or fail decision. * * Under most circumstances, Strategies should not need to call this * function. It exists primarily to allow previous authentication state * to be restored, for example from an HTTP session. * */ class PassResult extends ValidationResult_1.ValidationResult { action(ctx) { return true; } static ρAnn() { return { "name": "PassResult" }; } } exports.PassResult = PassResult; }); unwrapExports(PassResult_1); var PassResult_2 = PassResult_1.PassResult; var RedirectResult_1 = createCommonjsModule(function (module, exports) { Object.defineProperty(exports, "__esModule", { value: true }); exports.RedirectResult = void 0; /** * Redirect to `url` with optional `status`, defaulting to 302. * * Strategies should return this function to redirect the user (via their * user agent) to a third-party website for authentication. * * @param {String} url * @param {Number} status * @api public */ class RedirectResult extends ValidationResult_1.ValidationResult { constructor(url, status = 302) { super(); this.url = url; this.status = status; } /** * execute. * * @param {Context} ctx * @returns {Promise<void>} * @memberof RedirectResult */ action(ctx) { ctx.status = this.status; ctx.redirect(this.url); } static ρAnn() { return { "name": "RedirectResult" }; } } exports.RedirectResult = RedirectResult; }); unwrapExports(RedirectResult_1); var RedirectResult_2 = RedirectResult_1.RedirectResult; var SuccessResult_1 = createCommonjsModule(function (module, exports) { Object.defineProperty(exports, "__esModule", { value: true }); exports.SuccessResult = void 0; /** * Authenticate `user`, with optional `info`. * * Strategies should return this action to successfully authenticate a * user. `user` should be an object supplied by the application after it * has been given an opportunity to verify credentials. `info` is an * optional argument containing additional user information. This is * useful for third-party authentication strategies to pass profile * details. * * @param {Object} user * @param {Object} info * @api public */ class SuccessResult extends ValidationResult_1.ValidationResult { constructor(options, user, info) { super(); this.options = options; this.user = user; this.info = info; } async action(ctx, callback) { let user = this.user; let info = this.info || {}; if (callback) { return callback(null, user, info); } let msg; let options = this.options; if (options.successFlash) { var flash = options.successFlash; if (typeof flash === 'string') { flash = { type: 'success', message: flash }; } flash.type = flash.type || 'success'; var type = flash.type || info.type || 'success'; msg = flash.message || info.message || info; if (typeof msg === 'string') { ctx.session.flash = { type: type, message: msg }; } } if (options.successMessage) { if (!(info.type in ctx.session.message)) { ctx.session.message[info.type] = []; } ctx.session.message[info.type].push(info.message); } if (options.userProperty) { ctx.state[options.userProperty] = user; } await ctx.login(user); if (options.authInfo !== false) { ctx.state.authInfo = await ctx.passport.transformAuthInfo(info, ctx); } if (options.successReturnToOrRedirect) { let url = options.successReturnToOrRedirect; if (ctx.session && ctx.session.returnTo) { url = ctx.session.returnTo; delete ctx.session.returnTo; } return ctx.redirect(url); } if (options.successRedirect) { return ctx.redirect(options.successRedirect); } } static ρAnn() { return { "name": "SuccessResult" }; } } exports.SuccessResult = SuccessResult; }); unwrapExports(SuccessResult_1); var SuccessResult_2 = SuccessResult_1.SuccessResult; var results = createCommonjsModule(function (module, exports) { Object.defineProperty(exports, "__esModule", { value: true }); tslib.__exportStar(ValidationResult_1, exports); tslib.__exportStar(FailResult_1, exports); tslib.__exportStar(PassResult_1, exports); tslib.__exportStar(RedirectResult_1, exports); tslib.__exportStar(SuccessResult_1, exports); tslib.__exportStar(ValidationResult_1, exports); }); unwrapExports(results); var Strategy_1 = createCommonjsModule(function (module, exports) { Object.defineProperty(exports, "__esModule", { value: true }); exports.Strategy = void 0; let Strategy = class Strategy { static ρAnn() { return { "name": "Strategy", "params": { "authenticate": ["ctx", "options"] } }; } }; tslib.__decorate([ components.Input(), tslib.__metadata("design:type", String) ], Strategy.prototype, "name", void 0); tslib.__decorate([ ioc.Inject(IAuthenticator.AuthenticatorToken), tslib.__metadata("design:type", Object) ], Strategy.prototype, "authenticator", void 0); Strategy = tslib.__decorate([ ioc.Abstract() ], Strategy); exports.Strategy = Strategy; }); unwrapExports(Strategy_1); var Strategy_2 = Strategy_1.Strategy; var SessionStrategy_1 = createCommonjsModule(function (module, exports) { Object.defineProperty(exports, "__esModule", { value: true }); exports.SessionStrategy = void 0; /** * session. * * @export * @class SessionStrategy * @extends {Strategy} */ class SessionStrategy extends Strategy_1.Strategy { /** * `SessionStrategy` constructor. * */ constructor() { super(); this.name = 'session'; } /** * Authenticate request based on the current session state. * * The session authentication strategy uses the session to restore any login * state across requests. If a login session has been established, `req.user` * will be populated with the current user. * * This strategy is registered automatically by Passport. * */ async authenticate(ctx, options = {}) { if (!ctx.passport) { throw new Error('passport.initialize() middleware not in use'); } let su; if (ctx.session.passport) { su = ctx.session.passport.user; } if (su || su === 0) { // NOTE: Stream pausing is desirable in the case where later middleware is // listening for events emitted from request. For discussion on the // matter, refer to: https://github.com/jaredhanson/passport/pull/106 const user = await ctx.passport.deserializeUser(su, ctx); if (!user) { ctx.session.passport.user = undefined; return new results.PassResult(); } const property = ctx.passport.userProperty; ctx.state[property] = user; } return new results.PassResult(); } static ρAnn() { return { "name": "SessionStrategy" }; } } exports.SessionStrategy = SessionStrategy; }); unwrapExports(SessionStrategy_1); var SessionStrategy_2 = SessionStrategy_1.SessionStrategy; var LocalStrategy_1 = createCommonjsModule(function (module, exports) { Object.defineProperty(exports, "__esModule", { value: true }); exports.LocalStrategy = void 0; /** * Local authenticate strategy * * @export * @class LocalStrategy * @extends {Strategy} * @implements {AfterInit} */ let LocalStrategy = class LocalStrategy extends Strategy_1.Strategy { async onAfterInit() { if (!this.name) { this.name = 'local'; } if (!this.usernameField) { this.usernameField = 'username'; } if (!this.passwordField) { this.passwordField = 'password'; } } async authenticate(ctx, options) { let username = ctx.request.body[this.usernameField] || ctx.query[this.usernameField]; let password = ctx.request.body[this.passwordField] || ctx.query[this.passwordField]; let { user, info } = await this.verify(username, password, ctx); if (!user) { // TODO, not sure 401 is the correct meaning return new results.FailResult(info, 401); } return new results.SuccessResult(options, user, info); } static ρAnn() { return { "name": "LocalStrategy", "params": { "authenticate": ["ctx", "options"] } }; } }; tslib.__decorate([ components.Input(), tslib.__metadata("design:type", Function) ], LocalStrategy.prototype, "verify", void 0); tslib.__decorate([ components.Input(), tslib.__metadata("design:type", Object) ], LocalStrategy.prototype, "usernameField", void 0); tslib.__decorate([ components.Input(), tslib.__metadata("design:type", Object) ], LocalStrategy.prototype, "passwordField", void 0); LocalStrategy = tslib.__decorate([ components.Component({ selector: 'local' }) ], LocalStrategy); exports.LocalStrategy = LocalStrategy; }); unwrapExports(LocalStrategy_1); var LocalStrategy_2 = LocalStrategy_1.LocalStrategy; var JwtStrategy_1 = createCommonjsModule(function (module, exports) { Object.defineProperty(exports, "__esModule", { value: true }); exports.JwtRequest = exports.JwtStrategy = void 0; /** * Jwt authenticate strategy */ let JwtStrategy = class JwtStrategy extends Strategy_1.Strategy { async onAfterInit() { if (!this.name) { this.name = 'jwt'; } if (this.secretOrKey) { if (this.secretOrKeyProvider) { throw new TypeError('JwtStrategy has been given both a secretOrKey and a secretOrKeyProvider'); } this.secretOrKeyProvider = async (request, rawJwtToken) => { return this.secretOrKey; }; } if (!this.secretOrKeyProvider) { throw new TypeError('JwtStrategy requires a secret or key'); } if (!this.verify) { throw new TypeError('JwtStrategy requires a verify'); } if (!this.jwtFromRequest) { throw new TypeError('JwtStrategy requires a function to retrieve jwt from requests (see option jwtFromRequest)'); } } async authenticate(ctx, options) { let token = this.jwtFromRequest(ctx.request); if (!token) { return new results.FailResult('No auth token', 401); } let secretOrKey = this.secretOrKey = await this.secretOrKeyProvider(ctx.request, token); let payload = await new Promise((r, j) => { jsonwebtoken.verify(token, secretOrKey, { audience: this.audience, issuer: this.issuer, algorithms: this.algorithms, ignoreExpiration: this.ignoreExpiration }, (err, decoded) => { if (err) { j(err); } else { r(decoded); } }); }); let { user, info } = await this.verify(payload, ctx); if (!user) { // TODO, not sure 401 is the correct meaning return new results.FailResult(info, 401); } return new results.SuccessResult(options, user, info); } sign(payload, secretOrKey, options) { let defer = ioc.PromiseUtil.defer(); jsonwebtoken.sign(payload, secretOrKey || this.secretOrKey, Object.assign({ audience: this.audience, issuer: this.issuer }, (options || {}) // ignoreExpiration: this.ignoreExpiration ), (err, decoded) => { if (err) { defer.reject(err); } else { defer.resolve(decoded); } }); return defer.promise; } static ρAnn() { return { "name": "JwtStrategy", "params": { "authenticate": ["ctx", "options"], "sign": ["payload", "secretOrKey", "options"] } }; } }; tslib.__decorate([ components.Input(), tslib.__metadata("design:type", Function) ], JwtStrategy.prototype, "verify", void 0); tslib.__decorate([ components.Input(), tslib.__metadata("design:type", String) ], JwtStrategy.prototype, "issuer", void 0); tslib.__decorate([ components.Input(), tslib.__metadata("design:type", Object) ], JwtStrategy.prototype, "audience", void 0); tslib.__decorate([ components.Input(), tslib.__metadata("design:type", Array) ], JwtStrategy.prototype, "algorithms", void 0); tslib.__decorate([ components.Input(), tslib.__metadata("design:type", Boolean) ], JwtStrategy.prototype, "ignoreExpiration", void 0); tslib.__decorate([ components.Input(), tslib.__metadata("design:type", Object) ], JwtStrategy.prototype, "secretOrKey", void 0); tslib.__decorate([ components.Input(), tslib.__metadata("design:type", Function) ], JwtStrategy.prototype, "secretOrKeyProvider", void 0); tslib.__decorate([ components.Input(), tslib.__metadata("design:type", Function) ], JwtStrategy.prototype, "jwtFromRequest", void 0); JwtStrategy = tslib.__decorate([ components.Component({ selector: 'jwt' }) ], JwtStrategy); exports.JwtStrategy = JwtStrategy; const matcExp = /(\S+)\s+(\S+)/; function parseAuthHeader(hdrValue) { if (typeof hdrValue !== 'string') { return null; } var matches = hdrValue.match(matcExp); return matches && { scheme: matches[1], value: matches[2] }; } // Note: express http converts all headers // to lower case. const AUTH_HEADER = 'authorization', LEGACY_AUTH_SCHEME = 'JWT', BEARER_AUTH_SCHEME = 'bearer'; var JwtRequest; (function (JwtRequest) { function fromHeader(headerName) { return function (request) { var token = null; if (request.headers[headerName]) { token = request.headers[headerName]; } return token; }; } JwtRequest.fromHeader = fromHeader; function fromBodyField(fieldName) { return function (request) { var token = null; if (request.body && Object.prototype.hasOwnProperty.call(request.body, fieldName)) { token = request.body[fieldName]; } return token; }; } JwtRequest.fromBodyField = fromBodyField; function fromUrlQueryParameter(paramName) { return function (request) { let token = null, parsedUrl = url.parse(request.url, true); if (parsedUrl.query && Object.prototype.hasOwnProperty.call(parsedUrl.query, paramName)) { token = parsedUrl.query[paramName]; } return token; }; } JwtRequest.fromUrlQueryParameter = fromUrlQueryParameter; function fromAuthHeaderWithScheme(authScheme) { var authSchemeLower = authScheme.toLowerCase(); return function (request) { var token = null; if (request.headers[AUTH_HEADER]) { var authParams = parseAuthHeader(request.headers[AUTH_HEADER]); if (authParams && authSchemeLower === authParams.scheme.toLowerCase()) { token = authParams.value; } } return token; }; } JwtRequest.fromAuthHeaderWithScheme = fromAuthHeaderWithScheme; function fromAuthHeaderAsBearerToken() { return fromAuthHeaderWithScheme(BEARER_AUTH_SCHEME); } JwtRequest.fromAuthHeaderAsBearerToken = fromAuthHeaderAsBearerToken; function fromExtractors(extractors) { if (!Array.isArray(extractors)) { throw new TypeError('export function fromExtractors expects an array'); } return function (request) { var token = null; var index = 0; while (!token && index < length) { token = extractors[index].call(this, request); index++; } return token; }; } JwtRequest.fromExtractors = fromExtractors; /** * This extractor mimics the behavior of the v1.*.* extraction logic. * * This extractor exists only to provide an easy transition from the v1.*.* API to the v2.0.0 * API. * * This extractor first checks the auth header, if it doesn't find a token there then it checks the * specified body field and finally the url query parameters. * * @param options * authScheme: Expected scheme when JWT can be found in HTTP Authorize header. Default is JWT. * tokenBodyField: Field in request body containing token. Default is auth_token. * tokenQueryParameterName: Query parameter name containing the token. Default is auth_token. */ function versionOneCompatibility(options) { var authScheme = options.authScheme || LEGACY_AUTH_SCHEME, bodyField = options.tokenBodyField || 'auth_token', queryParam = options.tokenQueryParameterName || 'auth_token'; return function (request) { var authHeaderExtractor = fromAuthHeaderWithScheme(authScheme); var token = authHeaderExtractor(request); if (!token) { var bodyExtractor = fromBodyField(bodyField); token = bodyExtractor(request); } if (!token) { var queryExtractor = fromUrlQueryParameter(queryParam); token = queryExtractor(request); } return token; }; } JwtRequest.versionOneCompatibility = versionOneCompatibility; })(JwtRequest = exports.JwtRequest || (exports.JwtRequest = {})); }); unwrapExports(JwtStrategy_1); var JwtStrategy_2 = JwtStrategy_1.JwtRequest; var JwtStrategy_3 = JwtStrategy_1.JwtStrategy; var ContextExtends = createCommonjsModule(function (module, exports) { Object.defineProperty(exports, "__esModule", { value: true }); exports.contextExtends = void 0; /** * Intiate a login session for `user`. * * Options: * - `session` Save login state in session, defaults to `true` * * Examples: * * await req.logIn(user, { session: false }); * * @api public */ async function login(user) { if (!this.passport) { throw new Error('passport.initialize() middleware not in use'); } const property = (this.passport && this.passport.userProperty); this.state[property] = user; let obj; try { obj = await this.passport.serializeUser(user, this); } catch (err) { this.state[property] = null; throw err; } if (!this.session) { throw new Error('Should use session middleware before passport middleware'); } this.session.passport.user = obj; } /** * get current login user. * * @api public */ function getUser() { if (!this.passport || !this.session) { return null; } const property = this.passport.userProperty; return this.state[property]; } /** * get current login user roles. * * @api public */ function getRoles() { if (!this.passport || !this.session) { return null; } const property = this.passport.rolesProperty; return this.state[property]; } /** * Terminate an existing login session. * * @api public */ function logout() { if (!this.passport || !this.session) { return; } const property = this.passport.userProperty; delete this.state[property]; delete this.session.passport.user; } /** * Test if request is authenticated. * * @api public */ function isAuthenticated() { if (!this.passport) { return false; } const property = this.passport.userProperty; return (this.state[property]) ? true : false; } /** * Test if request is unauthenticated. * * @api public */ function isUnauthenticated() { return !this.isAuthenticated(); } function hasRole(...roles) { if (!this.passport) { return false; } if (!roles.length) { return true; } const property = this.passport.rolesProperty; if ((this.state[property])) { return this.state[property].some(role => roles.indexOf(role) > 0); } return false; } /** * context extends. * * @export * @param {BaseContext} ctx * @returns {void} */ function contextExtends(ctx) { // add passport http.IncomingMessage extensions if (ctx.hasOwnProperty('login') || ctx.hasOwnProperty('logout') || ctx.hasOwnProperty('isAuthenticated') || ctx.hasOwnProperty('isUnauthenticated')) { return; } Object.defineProperties(ctx, { login: { value: login, writable: false, enumerable: false }, logout: { value: logout, writable: false, enumerable: false }, getUser: { value: getUser, writable: false, enumerable: false }, hasRole: { value: hasRole, writable: false, enumerable: false }, getRoles: { value: getRoles, writable: false, enumerable: false }, isAuthenticated: { value: isAuthenticated, writable: false, enumerable: false }, isUnauthenticated: { value: isUnauthenticated, writable: false, enumerable: false } }); } exports.contextExtends = contextExtends; }); unwrapExports(ContextExtends); var ContextExtends_1 = ContextExtends.contextExtends; var Authenticator_1 = createCommonjsModule(function (module, exports) { Object.defineProperty(exports, "__esModule", { value: true }); exports.Authenticator = void 0; /** * `Authenticator` constructor. * */ let Authenticator = class Authenticator { constructor() { this._userProperty = 'user'; this._rolesProperty = 'roles'; this.strategies = new Map(); this.serializers = []; this.deserializers = []; this.infoTransformers = []; this.use(new SessionStrategy_1.SessionStrategy()); } get userProperty() { return this._userProperty; } get rolesProperty() { return this._rolesProperty; } /** * get strategy. * * @param {string} name * @returns {IStrategy} * @memberof IAuthenticator */ get(name) { return this.strategies.get(name); } use(name, strategy) { if (strategy === undefined) { strategy = name; name = strategy.name; } if (!name) { throw new Error('Authentication strategies must have a name'); } this.strategies.set(name, strategy); return this; } /** * Un-utilize the `strategy` with given `name`. * * In typical applications, the necessary authentication strategies are static, * configured once and always available. As such, there is often no need to * invoke this function. * * However, in certain situations, applications may need dynamically configure * and de-configure authentication strategies. The `use()`/`unuse()` * combination satisfies these scenarios. * * Examples: * * passport.unuse('legacy-api'); * */ unuse(name) { this.strategies.delete(name); return this; } /** * Passport's primary initialization middleware. * * Intializes Passport for incoming requests, allowing * authentication strategies to be applied. * * If sessions are being utilized, applications must set up Passport with * functions to serialize a user into and out of a session. For example, a * common pattern is to serialize just the user ID into the session (due to the * fact that it is desirable to store the minimum amount of data in a session). * When a subsequent request arrives for the session, the full User object can * be loaded from the database by ID. * * Note that additional middleware is required to persist login state, so we * must use the `connect.session()` middleware _before_ `passport.initialize()`. * * If sessions are being used, this middleware must be in use by the * Koa application for Passport to operate. If the application is * entirely stateless (not using sessions), this middleware is not necessary, * but its use will not have any adverse impact. * * Options: * - `userProperty` Property to set on `ctx.state` upon login, defaults to _user_ * * Examples: * app.use(connect.cookieParser()); * * app.use(connect.session({ secret: 'keyboard cat' })); * app.use(passport.initialize()); * app.use(passport.initialize({ userProperty: 'currentUser' })); * app.use(passport.session()); * * passport.serializeUser(function(user, done) { * done(null, user.id); * }); * * passport.deserializeUser(function(id, done) { * User.findById(id, function (err, user) { * done(err, user); * }); * }); * */ initialize(options = {}) { this._userProperty = options.userProperty || 'user'; this._rolesProperty = options.rolesProperty || 'roles'; return async (ctx, next) => { ctx.passport = this; const session = ctx.session; if (!session) { throw new Error('Session middleware is needed with passport middleware!'); } if (!('passport' in session)) { ctx.session.passport = { user: undefined }; } if (!('message' in session)) { session.message = {}; } ctx.session = session; ContextExtends.contextExtends(ctx); await next(); }; } authenticate(strategyNames, options = {}, callback) { if (ioc.isFunction(options)) { callback = options; options = {}; } let multi = true; // Cast `strategy` to an array, allowing authentication to pass through a chain of // strategies. The first strategy to succeed, redirect, or error will halt // the chain. Authentication failures will proceed through each strategy in // series, ultimately failing if all strategies fail. // // This is typically used on API endpoints to allow clients to authenticate // using their preferred choice of Basic, Digest, token-based schemes, etc. // It is not feasible to construct a chain of multiple strategies that involve // redirection (for example both Facebook and Twitter), since the first one to // redirect will halt the chain. if (ioc.isString(strategyNames)) { strategyNames = [strategyNames]; multi = false; } return async (ctx, next) => { // accumulator for failures from each strategy in the chain const failures = ctx.failures = []; await ioc.chain(strategyNames.map(strategyName => async (ctx1, step) => { const strategy = this.strategies.get(strategyName); if (!strategy) { throw new Error(`Unknown authentication strategy "${strategyName}"`); } try { const res = await strategy.authenticate(ctx1, options); if (res instanceof results.FailResult) { res.action(ctx1); } else if (res instanceof results.SuccessResult || res instanceof results.RedirectResult) { await res.action(ctx1); } else { await res.action(ctx1, callback); return step(); } } catch (error) { new results.FailResult(error.toString(), 401).action(ctx1); } }), ctx); if (!failures.length) { return await next(); } if (callback) { if (!multi) { return callback(null, false, failures[0].challenge, failures[0].status); } else { const challenges = failures.map(f => f.challenge); const statuses = failures.map(f => f.status); return callback(null, false, challenges, statuses); } } // Strategies are ordered by priority. For the purpose of flashing a // message, the first failure will be displayed. // const challenge = (failures[0] || {}).challenge || {}; if (options.failureMessage && failures[0].challenge.type) { const challenge = failures[0].challenge; if (!(challenge.type in ctx.session.message)) { ctx.session.message[challenge.type] = []; } ctx.session.message[challenge.type].push(challenge.messages); } if (options.failureRedirect) { return ctx.redirect(options.failureRedirect); } // When failure handling is not delegated to the application, the default // is to respond with 401 Unauthorized. Note that the WWW-Authenticate // header will be set according to the strategies in use (see // actions#fail). If multiple strategies failed, each of their challenges // will be included in the response. const rchallenge = []; let rstatus; let status; for (const failure of failures) { status = failure.status; rstatus = rstatus || status; if (ioc.isString(failure.challenge)) { rchallenge.push(failure.challenge); } } ctx.status = rstatus || 401; if (ctx.status === 401 && rchallenge.length) { ctx.set('WWW-Authenticate', rchallenge); } if (options.failWithError) { throw new errors.AuthenticationError(rstatus, http.STATUS_CODES[ctx.status]); } // ctx.res.statusMessage = http.STATUS_CODES[ctx.status]; ctx.response.message = http.STATUS_CODES[ctx.status]; ctx.res.end(http.STATUS_CODES[ctx.status]); throw new mvc.UnauthorizedError(ctx.response.message); }; } /** * Middleware that will authorize a third-party account using the given * `strategy` name, with optional `options`. * * If authorization is successful, the result provided by the strategy's verify * callback will be assigned to `ctx.state.account`. The existing login session and * `ctx.state.user` will be unaffected. * * This function is particularly useful when connecting third-party accounts * to the local account of a user that is currently authenticated. * * Examples: * * passport.authorize('twitter-authz', { failureRedirect: '/account' }); */ authorize(strategy, options = {}, callback) { options.userProperty = 'account'; return this.authenticate(strategy, options, callback); } /** * Middleware that will restore login state from a session. * * Web applications typically use sessions to maintain login state between * requests. For example, a user will authenticate by entering credentials into * a form which is submitted to the server. If the credentials are valid, a * login session is established by setting a cookie containing a session * identifier in the user's web browser. The web browser will send this cookie * in subsequent requests to the server, allowing a session to be maintained. * * If sessions are being utilized, and a login session has been established, * this middleware will populate `req.user` with the current user. * * Note that sessions are not strictly required for Passport to operate. * However, as a general rule, most web applications will make use of sessions. * An exception to this rule would be an API server, which expects each HTTP * request to provide credentials in an Authorization header. * * Examples: * * app.use(connect.cookieParser()); * app.use(connect.session({ secret: 'keyboard cat' })); * app.use(passport.initialize()); * app.use(passport.session()); * * Options: * - `pauseStream` Pause the request stream before deserializing the user * object from the session. Defaults to _false_. Should * be set to true in cases where middleware consuming the * request body is configured after passport and the * deserializeUser method is asynchronous. * * @api public */ session(options) { return this.authenticate('session', options); } async serializeUser(user, ctx) { if (typeof user === 'function') { return this.serializers.push(user); } for (const layer of this.serializers) { const obj = await layer(user, ctx); if (obj || obj === 0) { return obj; } } throw new Error('Failed to serialize user into session'); } async deserializeUser(obj, ctx) { if (ioc.isFunction(obj)) { return this.deserializers.push(obj); } for (const layer of this.deserializers) { const user = await layer(obj, ctx); if (user) { return user; } else if (user === null || user === false) { return false; } } throw new Error('Failed to deserialize user out of session'); } async transformAuthInfo(info, ctx) { if (ioc.isFunction(info)) { return this.infoTransformers.push(info); } // private implementation that traverses the chain of transformers, // attempting to transform auth info for (const layer of this.infoTransformers) { const tinfo = await layer(info, ctx); if (tinfo) { return tinfo; } } return info; } static ρAnn() { return { "name": "Authenticator", "params": { "get": ["name"], "use": ["name", "strategy"], "unuse": ["name"], "initialize": ["options"], "authenticate": ["strategyNames", "options", "callback"], "authorize": ["strategy", "options", "callback"], "session": ["options"], "serializeUser": ["user", "ctx"], "deserializeUser": ["obj", "ctx"], "transformAuthInfo": ["info", "ctx"] } }; } }; Authenticator = tslib.__decorate([ ioc.Singleton(IAuthenticator.AuthenticatorToken), tslib.__metadata("design:paramtypes", []) ], Authenticator); exports.Authenticator = Authenticator; }); unwrapExports(Authenticator_1); var Authenticator_2 = Authenticator_1.Authenticator; var StrategySelectorHandle_1 = createCommonjsModule(function (module, exports) { Object.defineProperty(exports, "__esModule", { value: true }); exports.StrategySelectorHandle = void 0; class StrategySelectorHandle extends components.ComponentSelectorHandle { getSelector(template, compdr) { return ioc.isMetadataObject(template) ? template.strategy : null; } static ρAnn() { return { "name": "StrategySelectorHandle" }; } } exports.StrategySelectorHandle = StrategySelectorHandle; }); unwrapExports(StrategySelectorHandle_1); var StrategySelectorHandle_2 = StrategySelectorHandle_1.StrategySelectorHandle; var SerializeUser_1 = createCommonjsModule(function (module, exports) { Object.defineProperty(exports, "__esModule", { value: true }); exports.SerializeUser = void 0; let SerializeUser = class SerializeUser { static ρAnn() { return { "name": "SerializeUser", "params": { "serializeUser": ["user", "ctx"] } }; } }; SerializeUser = tslib.__decorate([ ioc.Abstract() ], SerializeUser); exports.SerializeUser = SerializeUser; }); unwrapExports(SerializeUser_1); var SerializeUser_2 = SerializeUser_1.SerializeUser; var DeserializeUser_1 = createCommonjsModule(function (module, exports) { Object.defineProperty(exports, "__esModule", { value: true }); exports.DeserializeUser = void 0; let DeserializeUser = class DeserializeUser { static ρAnn() { return { "name": "DeserializeUser", "params": { "deserializeUser": ["obj", "ctx"] } }; } }; DeserializeUser = tslib.__decorate([ ioc.Abstract() ], DeserializeUser); exports.DeserializeUser = DeserializeUser; }); unwrapExports(DeserializeUser_1); var DeserializeUser_2 = DeserializeUser_1.DeserializeUser; var TransformAuthInfo_1 = createCommonjsModule(function (module, exports) { Object.defineProperty(exports, "__esModule", { value: true }); exports.TransformAuthInfo = void 0; let TransformAuthInfo = class TransformAuthInfo { static ρAnn() { return { "name": "TransformAuthInfo", "params": { "authInfo": ["user", "ctx"] } }; } }; TransformAuthInfo = tslib.__decorate([ ioc.Abstract() ], TransformAuthInfo); exports.TransformAuthInfo = TransformAuthInfo; }); unwrapExports(TransformAuthInfo_1); var TransformAuthInfo_2 = TransformAuthInfo_1.TransformAuthInfo; var services = createCommonjsModule(function (module, exports) { Object.defineProperty(exports, "__esModule", { value: true }); tslib.__exportStar(SerializeUser_1, exports); tslib.__exportStar(DeserializeUser_1, exports); tslib.__exportStar(TransformAuthInfo_1, exports); }); unwrapExports(services); var PassportBuildService_1 = createCommonjsModule(function (module, exports) { Object.defin