UNPKG

@strongnguyen/oidc-provider

Version:

OAuth 2.0 Authorization Server implementation for Node.js with OpenID Connect

129 lines (97 loc) 3.81 kB
/* eslint-disable camelcase, max-len */ const errors = require('../../errors'); const get = require('../../_/get'); const instance = require('../../weak_cache'); const Prompt = require('../prompt'); const Check = require('../check'); module.exports = () => new Prompt( { name: 'login', requestable: true }, (ctx) => { const { oidc } = ctx; return { ...(oidc.params.max_age === undefined ? undefined : { max_age: oidc.params.max_age }), ...(oidc.params.login_hint === undefined ? undefined : { login_hint: oidc.params.login_hint }), ...(oidc.params.id_token_hint === undefined ? undefined : { id_token_hint: oidc.params.id_token_hint }), }; }, new Check('no_session', 'End-User authentication is required', (ctx) => { const { oidc } = ctx; if (oidc.session.accountId) { return Check.NO_NEED_TO_PROMPT; } return Check.REQUEST_PROMPT; }), new Check('max_age', 'End-User authentication could not be obtained', (ctx) => { const { oidc } = ctx; if (oidc.params.max_age === undefined) { return Check.NO_NEED_TO_PROMPT; } if (!oidc.session.accountId) { return Check.REQUEST_PROMPT; } if (oidc.session.past(oidc.params.max_age) && (!ctx.oidc.result || !ctx.oidc.result.login)) { return Check.REQUEST_PROMPT; } return Check.NO_NEED_TO_PROMPT; }), new Check('id_token_hint', 'id_token_hint and authenticated subject do not match', async (ctx) => { const { oidc } = ctx; if (oidc.entities.IdTokenHint === undefined) { return Check.NO_NEED_TO_PROMPT; } const { payload } = oidc.entities.IdTokenHint; let sub = oidc.session.accountId; if (sub === undefined) { return Check.REQUEST_PROMPT; } if (oidc.client.subjectType === 'pairwise') { sub = await instance(oidc.provider).configuration('pairwiseIdentifier')(ctx, sub, oidc.client); } if (payload.sub !== sub) { return Check.REQUEST_PROMPT; } return Check.NO_NEED_TO_PROMPT; }), new Check('claims_id_token_sub_value', 'requested subject could not be obtained', async (ctx) => { const { oidc } = ctx; if (!oidc.claims.id_token || !oidc.claims.id_token.sub || !('value' in oidc.claims.id_token.sub)) { return Check.NO_NEED_TO_PROMPT; } let sub = oidc.session.accountId; if (sub === undefined) { return Check.REQUEST_PROMPT; } if (oidc.client.subjectType === 'pairwise') { sub = await instance(oidc.provider).configuration('pairwiseIdentifier')(ctx, sub, oidc.client); } if (oidc.claims.id_token.sub.value !== sub) { return Check.REQUEST_PROMPT; } return Check.NO_NEED_TO_PROMPT; }, ({ oidc }) => ({ sub: oidc.claims.id_token.sub })), new Check('essential_acrs', 'none of the requested ACRs could not be obtained', (ctx) => { const { oidc } = ctx; const request = get(oidc.claims, 'id_token.acr', {}); if (!request || !request.essential || !request.values) { return Check.NO_NEED_TO_PROMPT; } if (!Array.isArray(oidc.claims.id_token.acr.values)) { throw new errors.InvalidRequest('invalid claims.id_token.acr.values type'); } if (request.values.includes(oidc.acr)) { return Check.NO_NEED_TO_PROMPT; } return Check.REQUEST_PROMPT; }, ({ oidc }) => ({ acr: oidc.claims.id_token.acr })), new Check('essential_acr', 'requested ACR could not be obtained', (ctx) => { const { oidc } = ctx; const request = get(oidc.claims, 'id_token.acr', {}); if (!request || !request.essential || !request.value) { return Check.NO_NEED_TO_PROMPT; } if (request.value === oidc.acr) { return Check.NO_NEED_TO_PROMPT; } return Check.REQUEST_PROMPT; }, ({ oidc }) => ({ acr: oidc.claims.id_token.acr })), );