oidc-provider
Advanced tools
Comparing version 8.0.0 to 8.1.0
@@ -32,4 +32,3 @@ import { InvalidRequest } from '../../helpers/errors.js'; | ||
// checking for response_type presence disables the need for PKCE for device_code grant | ||
if (typeof params.response_type === 'string' && params.response_type.includes('code')) { | ||
if (params.response_type.includes('code')) { | ||
if ( | ||
@@ -36,0 +35,0 @@ !params.code_challenge |
@@ -15,3 +15,3 @@ import { InvalidRequest } from '../../helpers/errors.js'; | ||
for (const prompt of prompts) { // eslint-disable-line no-restricted-syntax | ||
for (const prompt of prompts) { | ||
if (!supported.has(prompt)) { | ||
@@ -18,0 +18,0 @@ throw new InvalidRequest('unsupported prompt value requested'); |
@@ -46,3 +46,3 @@ import { InvalidScope } from '../../helpers/errors.js'; | ||
const allowList = new Set(client.scope.split(' ')); | ||
// eslint-disable-next-line no-restricted-syntax | ||
for (const scope of scopes.filter(Set.prototype.has.bind(statics))) { | ||
@@ -49,0 +49,0 @@ if (!allowList.has(scope)) { |
@@ -172,3 +172,3 @@ import noCache from '../../shared/no_cache.js'; | ||
use(() => checkWebMessageUri, A, PAR ); | ||
use(() => checkPKCE, A, DA, PAR ); | ||
use(() => checkPKCE, A, PAR ); | ||
use(() => checkClaims, A, DA, PAR, BA); | ||
@@ -175,0 +175,0 @@ use(() => checkMaxAge, A, DA, PAR, BA); |
@@ -10,3 +10,3 @@ import * as url from 'node:url'; | ||
/* eslint-disable no-restricted-syntax, no-await-in-loop */ | ||
/* eslint-disable no-await-in-loop */ | ||
@@ -13,0 +13,0 @@ export default async function interactions(resumeRouteName, ctx, next) { |
@@ -190,3 +190,2 @@ import * as JWT from '../../helpers/jwt.js'; | ||
if (isBackchannelAuthentication) { | ||
// eslint-disable-next-line no-restricted-syntax | ||
for (const claim of ['exp', 'iat', 'nbf', 'jti']) { | ||
@@ -193,0 +192,0 @@ if (!(claim in payload)) { |
@@ -12,3 +12,3 @@ /* | ||
for (const [param, value] of Object.entries(ctx.oidc.params)) { // eslint-disable-line no-restricted-syntax, max-len | ||
for (const [param, value] of Object.entries(ctx.oidc.params)) { | ||
if (value !== undefined) { | ||
@@ -15,0 +15,0 @@ if (JAR && (param !== 'client_id' && param !== 'request')) { |
@@ -13,11 +13,17 @@ /* eslint-disable max-len */ | ||
authorization_endpoint: ctx.oidc.urlFor('authorization'), | ||
device_authorization_endpoint: features.deviceFlow.enabled ? ctx.oidc.urlFor('device_authorization') : undefined, | ||
device_authorization_endpoint: features.deviceFlow.enabled | ||
? ctx.oidc.urlFor('device_authorization') | ||
: undefined, | ||
claims_parameter_supported: features.claimsParameter.enabled, | ||
claims_supported: [...config.claimsSupported], | ||
code_challenge_methods_supported: config.pkce.methods, | ||
end_session_endpoint: features.rpInitiatedLogout.enabled ? ctx.oidc.urlFor('end_session') : undefined, | ||
end_session_endpoint: features.rpInitiatedLogout.enabled | ||
? ctx.oidc.urlFor('end_session') | ||
: undefined, | ||
grant_types_supported: [...config.grantTypes], | ||
issuer: ctx.oidc.issuer, | ||
jwks_uri: ctx.oidc.urlFor('jwks'), | ||
registration_endpoint: features.registration.enabled ? ctx.oidc.urlFor('registration') : undefined, | ||
registration_endpoint: features.registration.enabled | ||
? ctx.oidc.urlFor('registration') | ||
: undefined, | ||
authorization_response_iss_parameter_supported: true, | ||
@@ -42,3 +48,5 @@ response_modes_supported: ['form_post', 'fragment', 'query'], | ||
if (pushedAuthorizationRequests.enabled) { | ||
ctx.body.pushed_authorization_request_endpoint = ctx.oidc.urlFor('pushed_authorization_request'); | ||
ctx.body.pushed_authorization_request_endpoint = ctx.oidc.urlFor( | ||
'pushed_authorization_request', | ||
); | ||
ctx.body.require_pushed_authorization_requests = pushedAuthorizationRequests.requirePushedAuthorizationRequests ? true : undefined; | ||
@@ -52,3 +60,5 @@ } | ||
ctx.body.require_request_uri_registration = requestObjects.requestUri && requestObjects.requireUriRegistration ? true : undefined; | ||
ctx.body.require_signed_request_object = requestObjects.requireSignedRequestObject ? true : undefined; | ||
ctx.body.require_signed_request_object = requestObjects.requireSignedRequestObject | ||
? true | ||
: undefined; | ||
@@ -128,3 +138,5 @@ if (features.encryption.enabled) { | ||
ctx.body.backchannel_user_code_parameter_supported = true; | ||
ctx.body.backchannel_authentication_request_signing_alg_values_supported = requestObjects.request ? config.requestObjectSigningAlgValues.filter((alg) => !alg.startsWith('HS')) : undefined; | ||
ctx.body.backchannel_authentication_request_signing_alg_values_supported = requestObjects.request | ||
? config.requestObjectSigningAlgValues.filter((alg) => !alg.startsWith('HS')) | ||
: undefined; | ||
} | ||
@@ -131,0 +143,0 @@ |
@@ -139,5 +139,5 @@ import * as crypto from 'node:crypto'; | ||
for (const clientId of clientIds) { // eslint-disable-line no-restricted-syntax | ||
for (const clientId of clientIds) { | ||
if (params.logout || clientId === state.clientId) { | ||
const client = await ctx.oidc.provider.Client.find(clientId); // eslint-disable-line no-await-in-loop, max-len | ||
const client = await ctx.oidc.provider.Client.find(clientId); // eslint-disable-line no-await-in-loop | ||
if (client) { | ||
@@ -144,0 +144,0 @@ const sid = session.sidFor(client.clientId); |
@@ -25,3 +25,3 @@ import instance from '../../helpers/weak_cache.js'; | ||
const allowList = new Set(client.scope.split(' ')); | ||
// eslint-disable-next-line no-restricted-syntax | ||
for (const scope of scopes.filter(Set.prototype.has.bind(statics))) { | ||
@@ -39,3 +39,2 @@ if (!allowList.has(scope)) { | ||
// eslint-disable-next-line no-restricted-syntax | ||
Object.values(ctx.oidc.resourceServers).forEach((resourceServer, i) => { | ||
@@ -42,0 +41,0 @@ if (i !== 0) { |
@@ -139,3 +139,2 @@ import { strict as assert } from 'node:assert'; | ||
if (details.missingResourceScopes) { | ||
// eslint-disable-next-line no-restricted-syntax | ||
for (const [indicator, scope] of Object.entries(details.missingResourceScopes)) { | ||
@@ -142,0 +141,0 @@ grant.addResourceScope(indicator, scope.join(' ')); |
@@ -123,3 +123,3 @@ import omitBy from '../helpers/_/omit_by.js'; | ||
const implementations = instance(provider).configuration('features.registration.policies'); | ||
for (const policy of policies) { // eslint-disable-line no-restricted-syntax | ||
for (const policy of policies) { | ||
await implementations[policy](ctx, properties); // eslint-disable-line no-await-in-loop | ||
@@ -236,3 +236,3 @@ } | ||
const implementations = instance(provider).configuration('features.registration.policies'); | ||
for (const policy of policies) { // eslint-disable-line no-restricted-syntax | ||
for (const policy of policies) { | ||
await implementations[policy](ctx, properties); // eslint-disable-line no-await-in-loop | ||
@@ -239,0 +239,0 @@ } |
@@ -1,2 +0,2 @@ | ||
/* eslint-disable no-restricted-syntax, no-continue, no-param-reassign */ | ||
/* eslint-disable no-continue, no-param-reassign */ | ||
@@ -3,0 +3,0 @@ import isPlainObject from './is_plain_object.js'; |
@@ -1,2 +0,2 @@ | ||
/* eslint-disable no-restricted-syntax, no-param-reassign, no-continue */ | ||
/* eslint-disable no-param-reassign, no-continue */ | ||
@@ -3,0 +3,0 @@ import isPlainObject from './is_plain_object.js'; |
@@ -1,2 +0,2 @@ | ||
import { createHash } from 'node:crypto'; | ||
import { createHash, X509Certificate } from 'node:crypto'; | ||
@@ -6,4 +6,7 @@ import * as base64url from './base64url.js'; | ||
export default function certThumbprint(cert) { | ||
return base64url.encodeBuffer( | ||
createHash('sha256') | ||
let digest; | ||
if (cert instanceof X509Certificate) { | ||
digest = createHash('sha256').update(cert.raw).digest(); | ||
} else { | ||
digest = createHash('sha256') | ||
.update( | ||
@@ -15,4 +18,6 @@ Buffer.from( | ||
) | ||
.digest(), | ||
); | ||
.digest(); | ||
} | ||
return base64url.encodeBuffer(digest); | ||
} |
@@ -170,3 +170,2 @@ import * as url from 'node:url'; | ||
if (metadata.subject_type === 'pairwise') { | ||
// eslint-disable-next-line no-restricted-syntax | ||
for (const grant of ['urn:ietf:params:oauth:grant-type:device_code', 'urn:openid:params:grant-type:ciba']) { | ||
@@ -636,3 +635,2 @@ if (metadata.grant_types.includes(grant) && !['private_key_jwt', 'self_signed_tls_client_auth'].includes(metadata.token_endpoint_auth_method)) { | ||
syntax() { | ||
// eslint-disable-next-line no-restricted-syntax | ||
for (const [prop, regexp] of Object.entries(SYNTAX)) { | ||
@@ -639,0 +637,0 @@ if (regexp.exec(this[prop])) { |
@@ -8,3 +8,2 @@ export default (grant, requestParamScopes, resourceServers) => { | ||
// eslint-disable-next-line no-restricted-syntax | ||
for (const resourceServer of Object.values(resourceServers)) { | ||
@@ -11,0 +10,0 @@ grant.getResourceScopeFiltered(resourceServer.identifier(), requestParamScopes) |
@@ -16,3 +16,3 @@ import { JWA } from '../consts/index.js'; | ||
function featuresTypeErrorCheck({ features }) { | ||
for (const value of Object.values(features)) { // eslint-disable-line no-restricted-syntax | ||
for (const value of Object.values(features)) { | ||
if (typeof value === 'boolean') { | ||
@@ -304,3 +304,2 @@ throw new TypeError('Features are not enabled/disabled with a boolean value. See the documentation for more details.'); | ||
// eslint-disable-next-line no-restricted-syntax | ||
for (const mode of modes) { | ||
@@ -307,0 +306,0 @@ if (!['ping', 'poll'].includes(mode)) { |
@@ -1,2 +0,2 @@ | ||
/* eslint-disable no-plusplus, no-bitwise, no-param-reassign, no-restricted-syntax */ | ||
/* eslint-disable no-plusplus, no-bitwise, no-param-reassign */ | ||
@@ -3,0 +3,0 @@ import { createHmac } from 'node:crypto'; |
@@ -5,3 +5,3 @@ export default (source, target, grant) => { | ||
const granted = new Set(grant.getOIDCClaimsFiltered(new Set(requested))); | ||
// eslint-disable-next-line no-restricted-syntax | ||
for (const claim of requested) { | ||
@@ -8,0 +8,0 @@ // eslint-disable-next-line no-continue |
@@ -33,2 +33,3 @@ import { strict as assert, AssertionError } from 'node:assert'; | ||
default: | ||
return undefined; | ||
} | ||
@@ -35,0 +36,0 @@ |
@@ -32,3 +32,3 @@ /* eslint-disable no-unused-expressions */ | ||
let missing; | ||
for (const scope of oidc.requestParamOIDCScopes) { // eslint-disable-line no-restricted-syntax | ||
for (const scope of oidc.requestParamOIDCScopes) { | ||
if (!encounteredScopes.has(scope)) { | ||
@@ -53,3 +53,3 @@ missing ||= []; | ||
let missing; | ||
for (const claim of oidc.requestParamClaims) { // eslint-disable-line no-restricted-syntax | ||
for (const claim of oidc.requestParamClaims) { | ||
if (!encounteredClaims.has(claim) && !['sub', 'sid', 'auth_time', 'acr', 'amr', 'iss'].includes(claim)) { | ||
@@ -75,3 +75,2 @@ missing ||= []; | ||
// eslint-disable-next-line no-restricted-syntax | ||
for (const [indicator, resourceServer] of Object.entries(ctx.oidc.resourceServers)) { | ||
@@ -82,3 +81,3 @@ const encounteredScopes = new Set(oidc.grant.getResourceScopeEncountered(indicator).split(' ')); | ||
for (const scope of requestedScopes) { // eslint-disable-line no-restricted-syntax | ||
for (const scope of requestedScopes) { | ||
if (availableScopes.has(scope) && !encounteredScopes.has(scope)) { | ||
@@ -85,0 +84,0 @@ missing || (missing = {}); |
@@ -1,2 +0,2 @@ | ||
/* eslint-disable camelcase, max-len */ | ||
/* eslint-disable camelcase */ | ||
@@ -17,4 +17,8 @@ import * as errors from '../../errors.js'; | ||
...(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 }), | ||
...(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 }), | ||
}; | ||
@@ -49,82 +53,113 @@ }, | ||
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; | ||
} | ||
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; | ||
const { payload } = oidc.entities.IdTokenHint; | ||
let sub = oidc.session.accountId; | ||
if (sub === undefined) { | ||
return Check.REQUEST_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.client.subjectType === 'pairwise') { | ||
sub = await instance(oidc.provider).configuration('pairwiseIdentifier')( | ||
ctx, | ||
sub, | ||
oidc.client, | ||
); | ||
} | ||
if (payload.sub !== sub) { | ||
return Check.REQUEST_PROMPT; | ||
} | ||
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; | ||
} | ||
new Check( | ||
'claims_id_token_sub_value', | ||
'requested subject could not be obtained', | ||
async (ctx) => { | ||
const { oidc } = ctx; | ||
if (oidc.client.subjectType === 'pairwise') { | ||
sub = await instance(oidc.provider).configuration('pairwiseIdentifier')(ctx, sub, oidc.client); | ||
} | ||
if ( | ||
!oidc.claims.id_token | ||
|| !oidc.claims.id_token.sub | ||
|| !('value' in oidc.claims.id_token.sub) | ||
) { | ||
return Check.NO_NEED_TO_PROMPT; | ||
} | ||
if (oidc.claims.id_token.sub.value !== sub) { | ||
return Check.REQUEST_PROMPT; | ||
} | ||
let sub = oidc.session.accountId; | ||
if (sub === undefined) { | ||
return Check.REQUEST_PROMPT; | ||
} | ||
return Check.NO_NEED_TO_PROMPT; | ||
}, ({ oidc }) => ({ sub: oidc.claims.id_token.sub })), | ||
if (oidc.client.subjectType === 'pairwise') { | ||
sub = await instance(oidc.provider).configuration('pairwiseIdentifier')( | ||
ctx, | ||
sub, | ||
oidc.client, | ||
); | ||
} | ||
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 (oidc.claims.id_token.sub.value !== sub) { | ||
return Check.REQUEST_PROMPT; | ||
} | ||
if (!request || !request.essential || !request.values) { | ||
return Check.NO_NEED_TO_PROMPT; | ||
} | ||
}, | ||
({ oidc }) => ({ sub: oidc.claims.id_token.sub }), | ||
), | ||
if (!Array.isArray(oidc.claims.id_token.acr.values)) { | ||
throw new errors.InvalidRequest('invalid claims.id_token.acr.values type'); | ||
} | ||
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.values.includes(oidc.acr)) { | ||
return Check.NO_NEED_TO_PROMPT; | ||
} | ||
if (!request || !request.essential || !request.values) { | ||
return Check.NO_NEED_TO_PROMPT; | ||
} | ||
return Check.REQUEST_PROMPT; | ||
}, ({ oidc }) => ({ acr: oidc.claims.id_token.acr })), | ||
if (!Array.isArray(oidc.claims.id_token.acr.values)) { | ||
throw new errors.InvalidRequest('invalid claims.id_token.acr.values type'); | ||
} | ||
new Check('essential_acr', 'requested ACR could not be obtained', (ctx) => { | ||
const { oidc } = ctx; | ||
const request = get(oidc.claims, 'id_token.acr', {}); | ||
if (request.values.includes(oidc.acr)) { | ||
return Check.NO_NEED_TO_PROMPT; | ||
} | ||
if (!request || !request.essential || !request.value) { | ||
return Check.NO_NEED_TO_PROMPT; | ||
} | ||
return Check.REQUEST_PROMPT; | ||
}, | ||
({ oidc }) => ({ acr: oidc.claims.id_token.acr }), | ||
), | ||
if (request.value === oidc.acr) { | ||
return Check.NO_NEED_TO_PROMPT; | ||
} | ||
new Check( | ||
'essential_acr', | ||
'requested ACR could not be obtained', | ||
(ctx) => { | ||
const { oidc } = ctx; | ||
const request = get(oidc.claims, 'id_token.acr', {}); | ||
return Check.REQUEST_PROMPT; | ||
}, ({ oidc }) => ({ acr: 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 }), | ||
), | ||
); |
@@ -145,3 +145,2 @@ import { | ||
} else { | ||
// eslint-disable-next-line no-restricted-syntax | ||
for (const key of keys) { | ||
@@ -199,3 +198,2 @@ try { | ||
} else { | ||
// eslint-disable-next-line no-restricted-syntax | ||
for (const key of keys) { | ||
@@ -202,0 +200,0 @@ try { |
@@ -1,2 +0,2 @@ | ||
/* eslint-disable no-plusplus, no-restricted-syntax */ | ||
/* eslint-disable no-plusplus */ | ||
import { importJWK } from 'jose'; | ||
@@ -3,0 +3,0 @@ |
@@ -337,3 +337,3 @@ /* eslint-disable max-classes-per-file */ | ||
for (const alg of algs) { // eslint-disable-line no-restricted-syntax | ||
for (const alg of algs) { | ||
if (!( | ||
@@ -348,3 +348,2 @@ alg.startsWith('HS') | ||
// eslint-disable-next-line no-restricted-syntax | ||
for (const alg of algs) { | ||
@@ -351,0 +350,0 @@ if (alg.startsWith('HS')) { |
@@ -1,2 +0,1 @@ | ||
/* eslint-disable no-restricted-syntax */ | ||
/* eslint-disable no-unused-expressions */ | ||
@@ -3,0 +2,0 @@ /* eslint-disable no-param-reassign */ |
@@ -29,5 +29,5 @@ // eslint-disable-next-line import/order | ||
const minimal = 'Hydrogen'; | ||
const current = process.release.lts; | ||
if (!current || current.charCodeAt(0) < minimal.charCodeAt(0)) { | ||
attention.warn('Unsupported Node.js runtime version.'); | ||
const { lts: codename } = process.release || {}; | ||
if (!codename || codename.charCodeAt(0) < minimal.charCodeAt(0)) { | ||
attention.warn('Unsupported runtime. Use Node.js v18.x LTS, or a later LTS release.'); | ||
} | ||
@@ -34,0 +34,0 @@ |
@@ -67,3 +67,3 @@ import Debug from 'debug'; | ||
for (const [param, { // eslint-disable-line no-restricted-syntax | ||
for (const [param, { | ||
Err, check, flag, method, recovery, | ||
@@ -70,0 +70,0 @@ }] of AD_ACTA_CHECKS) { |
@@ -10,3 +10,2 @@ /* eslint-disable no-underscore-dangle */ | ||
if (ctx.oidc.params.scope && !ctx.oidc.params.resource) { | ||
// eslint-disable-next-line no-restricted-syntax | ||
ctx.oidc.params.scope = [...ctx.oidc.requestParamOIDCScopes].join(' '); | ||
@@ -59,3 +58,2 @@ } | ||
// eslint-disable-next-line no-restricted-syntax | ||
for (const identifier of resource) { | ||
@@ -62,0 +60,0 @@ let href; |
@@ -219,3 +219,3 @@ import { InvalidRequest, InvalidClientAuth } from '../helpers/errors.js'; | ||
for (const [prop, key] of Object.entries({ // eslint-disable-line no-restricted-syntax | ||
for (const [prop, key] of Object.entries({ | ||
tlsClientAuthSubjectDn: 'tls_client_auth_subject_dn', | ||
@@ -222,0 +222,0 @@ tlsClientAuthSanDns: 'tls_client_auth_san_dns', |
{ | ||
"name": "oidc-provider", | ||
"version": "8.0.0", | ||
"version": "8.1.0", | ||
"description": "OAuth 2.0 Authorization Server implementation for Node.js with OpenID Connect", | ||
@@ -88,3 +88,2 @@ "keywords": [ | ||
"helmet": "^6.0.0", | ||
"jose2": "npm:jose@^2.0.6", | ||
"koa-body": "^6.0.1", | ||
@@ -101,6 +100,3 @@ "koa-mount": "^4.0.0", | ||
"timekeeper": "^2.2.0" | ||
}, | ||
"engines": { | ||
"node": "18" | ||
} | ||
} |
# oidc-provider | ||
oidc-provider is an OAuth 2.0 Authorization Server with [OpenID Connect][openid-connect] and many | ||
additional features and standards implemented. | ||
This module provides an OAuth 2.0 ([RFC 6749][oauth2]) Authorization Server with support for OpenID Connect ([OIDC][openid-connect]) and many | ||
other additional features and standards. | ||
@@ -10,3 +10,2 @@ **Table of Contents** | ||
- [Certification](#certification) | ||
- [Get started](#get-started) | ||
- [Documentation & Configuration](#documentation--configuration) | ||
@@ -18,26 +17,27 @@ - [Recipes](#recipes) | ||
The following specifications are implemented by oidc-provider: | ||
The following specifications are implemented by oidc-provider (not exhaustive): | ||
_Note that not all features are enabled by default, check the configuration section on how to enable them._ | ||
- [RFC6749 - OAuth 2.0][oauth2] & [OpenID Connect Core 1.0][core] | ||
- [OpenID Connect Discovery 1.0][discovery] | ||
- [OpenID Connect Dynamic Client Registration 1.0][registration] and [RFC7591 - OAuth 2.0 Dynamic Client Registration Protocol][oauth2-registration] | ||
- [OpenID Connect RP-Initiated Logout 1.0][rpinitiated-logout] | ||
- [OpenID Connect Back-Channel Logout 1.0][backchannel-logout] | ||
- [OAuth 2.0 Form Post Response Mode][form-post] | ||
- [RFC7009 - OAuth 2.0 Token Revocation][revocation] | ||
- [RFC7592 - OAuth 2.0 Dynamic Client Registration Management Protocol][registration-management] | ||
- [RFC7636 - Proof Key for Code Exchange (PKCE)][pkce] | ||
- [RFC7662 - OAuth 2.0 Token Introspection][introspection] | ||
- [RFC8252 - OAuth 2.0 for Native Apps BCP (AppAuth)][oauth-native-apps] | ||
- [RFC8628 - OAuth 2.0 Device Authorization Grant (Device Flow)][device-flow] | ||
- [RFC8705 - OAuth 2.0 Mutual TLS Client Authentication and Certificate Bound Access Tokens (MTLS)][mtls] | ||
- [RFC8707 - OAuth 2.0 Resource Indicators][resource-indicators] | ||
- [RFC9101 - OAuth 2.0 JWT-Secured Authorization Request (JAR)][jar] | ||
- [RFC9126 - OAuth 2.0 Pushed Authorization Requests (PAR)][par] | ||
- [RFC9207 - OAuth 2.0 Authorization Server Issuer Identifier in Authorization Response][iss-auth-resp] | ||
- [Financial-grade API Security Profile 1.0 - Part 2: Advanced (FAPI)][fapi] | ||
- [JWT Secured Authorization Response Mode for OAuth 2.0 (JARM)][jarm] | ||
- [OpenID Connect Client Initiated Backchannel Authentication Flow - Core 1.0 (CIBA)][ciba] | ||
- [`RFC6749` - OAuth 2.0][oauth2] & [`OIDC` Core 1.0][core] | ||
- [OIDC `Discovery 1.0`][discovery] | ||
- Dynamic Client Registration | ||
- [OIDC `Dynamic Client Registration 1.0`][registration] | ||
- [`RFC7591` - OAuth 2.0 Dynamic Client Registration Protocol][oauth2-registration] | ||
- [`RFC7592` - OAuth 2.0 Dynamic Client Registration Management Protocol][registration-management] | ||
- [OIDC `RP-Initiated Logout 1.0`][rpinitiated-logout] | ||
- [OIDC `Back-Channel Logout 1.0`][backchannel-logout] | ||
- [`RFC7009` - OAuth 2.0 Token Revocation][revocation] | ||
- [`RFC7636` - Proof Key for Code Exchange (`PKCE`)][pkce] | ||
- [`RFC7662` - OAuth 2.0 Token Introspection][introspection] | ||
- [`RFC8252` - OAuth 2.0 for Native Apps BCP (`AppAuth`)][oauth-native-apps] | ||
- [`RFC8628` - OAuth 2.0 Device Authorization Grant (`Device Flow`)][device-flow] | ||
- [`RFC8705` - OAuth 2.0 Mutual TLS Client Authentication and Certificate Bound Access Tokens (`MTLS`)][mtls] | ||
- [`RFC8707` - OAuth 2.0 Resource Indicators][resource-indicators] | ||
- [`RFC9101` - OAuth 2.0 JWT-Secured Authorization Request (`JAR`)][jar] | ||
- [`RFC9126` - OAuth 2.0 Pushed Authorization Requests (`PAR`)][par] | ||
- [`RFC9207` - OAuth 2.0 Authorization Server Issuer Identifier in Authorization Response][iss-auth-resp] | ||
- [Financial-grade API Security Profile 1.0 - Part 2: Advanced (`FAPI 1.0`)][fapi] | ||
- [JWT Secured Authorization Response Mode for OAuth 2.0 (`JARM`)][jarm] | ||
- [OIDC Client Initiated Backchannel Authentication Flow (`CIBA`)][ciba] | ||
@@ -48,3 +48,2 @@ Supported Access Token formats: | ||
- [JSON Web Token (JWT) Profile for OAuth 2.0 Access Tokens][jwt-at] | ||
- [Platform-Agnostic Security Tokens (PASETO)][paseto-at] | ||
@@ -54,4 +53,4 @@ The following draft specifications are implemented by oidc-provider: | ||
- [JWT Response for OAuth Token Introspection - draft 10][jwt-introspection] | ||
- [Financial-grade API: Client Initiated Backchannel Authentication Profile (FAPI-CIBA) - Implementer's Draft 01][fapi-ciba] | ||
- [OAuth 2.0 Demonstration of Proof-of-Possession at the Application Layer (DPoP) - draft 11][dpop] | ||
- [Financial-grade API: Client Initiated Backchannel Authentication Profile (`FAPI-CIBA`) - Implementer's Draft 01][fapi-ciba] | ||
- [OAuth 2.0 Demonstration of Proof-of-Possession at the Application Layer (`DPoP`) - draft 11][dpop] | ||
@@ -67,9 +66,7 @@ Updates to draft specification versions are released as MINOR library versions, | ||
Filip Skokan has [certified][openid-certified-link] that [oidc-provider][npm-url] | ||
conforms to the following profiles of the OpenID Connect™ protocol | ||
conforms to the following profiles of the OpenID Connect™ protocol. | ||
- Basic OP, Implicit OP, Hybrid OP, Config OP, Dynamic OP, Form Post OP, 3rd Party-Init OP | ||
- Back-Channel OP, RP-Initiated OP | ||
- FAPI 1.0 Advanced Final (w/ Private Key JWT, MTLS, JARM, PAR) | ||
- FAPI 1.0 Second Implementer's Draft (w/ Private Key JWT, MTLS, PAR) | ||
- FAPI-CIBA OP (w/ Private Key JWT, MTLS, Ping mode, Poll mode) | ||
- Basic, Implicit, Hybrid, Config, Dynamic, Form Post, and 3rd Party-Init OP profiles | ||
- Back-Channel Logout and RP-Initiated Logout | ||
- FAPI 1.0 Advanced (w/ Private Key JWT, MTLS, JARM, PAR, CIBA) | ||
@@ -84,8 +81,2 @@ ## Sponsor | ||
## Get started | ||
You may check the [example folder](/example) or follow a [step by step example][example-repo] to see | ||
which of those fits your desired application setup. | ||
Also be sure to check the available configuration docs section. | ||
## [Documentation](/docs/README.md) & Configuration | ||
@@ -95,3 +86,3 @@ | ||
[how](/docs/README.md#mounting-oidc-provider). The provider allows to be extended and configured in | ||
various ways to fit a variety of uses. See the [documentation](/docs/README.md). | ||
various ways to fit a variety of uses. See the [documentation](/docs/README.md) and [example folder](/example). | ||
@@ -101,3 +92,3 @@ ```js | ||
const configuration = { | ||
// ... see /docs for available configuration | ||
// refer to the documentation for other available configuration | ||
clients: [{ | ||
@@ -120,3 +111,3 @@ client_id: 'foo', | ||
## Recipes | ||
Collection of useful configurations use cases are available over at [recipes](/recipes). | ||
Collection of useful configuration use cases are available over at [recipes](/recipes). | ||
@@ -136,3 +127,2 @@ | ||
[registration]: https://openid.net/specs/openid-connect-registration-1_0.html | ||
[form-post]: https://openid.net/specs/oauth-v2-form-post-response-mode-1_0.html | ||
[oauth2]: https://www.rfc-editor.org/rfc/rfc6749.html | ||
@@ -156,3 +146,2 @@ [oauth2-bearer]: https://www.rfc-editor.org/rfc/rfc6750.html | ||
[jwt-at]: https://www.rfc-editor.org/rfc/rfc9068.html | ||
[paseto-at]: https://paseto.io | ||
[support-sponsor]: https://github.com/sponsors/panva | ||
@@ -159,0 +148,0 @@ [par]: https://www.rfc-editor.org/rfc/rfc9126.html |
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
25
527621
13692
143