@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
JavaScript
'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