UNPKG

@strongnguyen/oidc-provider

Version:

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

96 lines (76 loc) 3.2 kB
/* eslint-disable no-unused-expressions */ /* eslint-disable camelcase */ const Prompt = require('../prompt'); const Check = require('../check'); const missingOIDCScope = Symbol(); const missingOIDCClaims = Symbol(); const missingResourceScopes = Symbol(); module.exports = () => new Prompt( { name: 'consent', requestable: true }, new Check('native_client_prompt', 'native clients require End-User interaction', 'interaction_required', (ctx) => { const { oidc } = ctx; if ( oidc.client.applicationType === 'native' && oidc.params.response_type !== 'none' && (!oidc.result || !('consent' in oidc.result)) ) { return Check.REQUEST_PROMPT; } return Check.NO_NEED_TO_PROMPT; }), new Check('op_scopes_missing', 'requested scopes not granted', (ctx) => { const { oidc } = ctx; const encounteredScopes = new Set(oidc.grant.getOIDCScopeEncountered().split(' ')); let missing; for (const scope of oidc.requestParamOIDCScopes) { // eslint-disable-line no-restricted-syntax if (!encounteredScopes.has(scope)) { missing || (missing = []); missing.push(scope); } } if (missing && missing.length) { ctx.oidc[missingOIDCScope] = missing; return Check.REQUEST_PROMPT; } return Check.NO_NEED_TO_PROMPT; }, ({ oidc }) => ({ missingOIDCScope: oidc[missingOIDCScope] })), new Check('op_claims_missing', 'requested claims not granted', (ctx) => { const { oidc } = ctx; const encounteredClaims = new Set(oidc.grant.getOIDCClaimsEncountered()); let missing; for (const claim of oidc.requestParamClaims) { // eslint-disable-line no-restricted-syntax if (!encounteredClaims.has(claim) && !['sub', 'sid', 'auth_time', 'acr', 'amr', 'iss'].includes(claim)) { missing || (missing = []); missing.push(claim); } } if (missing && missing.length) { ctx.oidc[missingOIDCClaims] = missing; return Check.REQUEST_PROMPT; } return Check.NO_NEED_TO_PROMPT; }, ({ oidc }) => ({ missingOIDCClaims: oidc[missingOIDCClaims] })), // checks resource server scopes new Check('rs_scopes_missing', 'requested scopes not granted', (ctx) => { const { oidc } = ctx; let missing; // eslint-disable-next-line no-restricted-syntax for (const [indicator, resourceServer] of Object.entries(ctx.oidc.resourceServers)) { const encounteredScopes = new Set(oidc.grant.getResourceScopeEncountered(indicator).split(' ')); const requestedScopes = ctx.oidc.requestParamScopes; const availableScopes = resourceServer.scopes; for (const scope of requestedScopes) { // eslint-disable-line no-restricted-syntax if (availableScopes.has(scope) && !encounteredScopes.has(scope)) { missing || (missing = {}); missing[indicator] || (missing[indicator] = []); missing[indicator].push(scope); } } } if (missing && Object.keys(missing).length) { ctx.oidc[missingResourceScopes] = missing; return Check.REQUEST_PROMPT; } return Check.NO_NEED_TO_PROMPT; }, ({ oidc }) => ({ missingResourceScopes: oidc[missingResourceScopes] })), );