Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

oidc-provider

Package Overview
Dependencies
Maintainers
1
Versions
339
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

oidc-provider - npm Package Compare versions

Comparing version 1.2.0 to 2.0.0-alpha.1.2.0

8

lib/actions/authorization/assign_defaults.js

@@ -7,5 +7,5 @@ 'use strict';

*/
module.exports = function* assignDefaults(next) {
const params = this.oidc.params;
const client = this.oidc.client;
module.exports = async function assignDefaults(ctx, next) {
const params = ctx.oidc.params;
const client = ctx.oidc.client;

@@ -20,3 +20,3 @@ if (!params.acr_values && client.defaultAcrValues) {

yield next;
await next();
};
'use strict';
module.exports = provider => function* authorizationEmit(next) {
if (this.oidc.result) {
provider.emit('interaction.ended', this);
module.exports = provider => async function authorizationEmit(ctx, next) {
if (ctx.oidc.result) {
provider.emit('interaction.ended', ctx);
} else {
provider.emit('authorization.accepted', this);
provider.emit('authorization.accepted', ctx);
}
yield next;
await next();
};

@@ -20,7 +20,7 @@ 'use strict';

*/
module.exports = provider => function* checkClaims(next) {
const params = this.oidc.params;
module.exports = provider => async function checkClaims(ctx, next) {
const params = ctx.oidc.params;
if (params.claims !== undefined && instance(provider).configuration('features.claimsParameter')) {
this.assert(params.response_type !== 'none', new errors.InvalidRequestError(
ctx.assert(params.response_type !== 'none', new errors.InvalidRequestError(
'claims parameter should not be combined with response_type none'));

@@ -32,28 +32,28 @@

} catch (err) {
return this.throw(new errors.InvalidRequestError('could not parse the claims parameter JSON'));
return ctx.throw(new errors.InvalidRequestError('could not parse the claims parameter JSON'));
}
})();
this.assert(_.isPlainObject(claims),
ctx.assert(_.isPlainObject(claims),
new errors.InvalidRequestError('claims parameter should be a JSON object'));
this.assert(claims.userinfo !== undefined || claims.id_token !== undefined,
ctx.assert(claims.userinfo !== undefined || claims.id_token !== undefined,
new errors.InvalidRequestError(
'claims parameter should have userinfo or id_token properties'));
this.assert(claims.userinfo === undefined || _.isPlainObject(claims.userinfo),
ctx.assert(claims.userinfo === undefined || _.isPlainObject(claims.userinfo),
new errors.InvalidRequestError('claims.userinfo should be an object'));
this.assert(claims.id_token === undefined || _.isPlainObject(claims.id_token),
ctx.assert(claims.id_token === undefined || _.isPlainObject(claims.id_token),
new errors.InvalidRequestError('claims.id_token should be an object'));
this.assert(params.response_type !== 'id_token' || !claims.userinfo,
ctx.assert(params.response_type !== 'id_token' || !claims.userinfo,
new errors.InvalidRequestError(
'claims.userinfo should not be used if access_token is not issued'));
this.oidc.claims = claims;
ctx.oidc.claims = claims;
}
if (params.max_age || this.oidc.client.requireAuthTime) {
_.merge(this.oidc.claims, { id_token: { auth_time: { essential: true } } });
if (params.max_age || ctx.oidc.client.requireAuthTime) {
_.merge(ctx.oidc.claims, { id_token: { auth_time: { essential: true } } });
}

@@ -64,6 +64,6 @@

if (acrValues) {
_.merge(this.oidc.claims, { id_token: { acr: { values: acrValues.split(' ') } } });
_.merge(ctx.oidc.claims, { id_token: { acr: { values: acrValues.split(' ') } } });
}
yield next;
await next();
};

@@ -13,14 +13,14 @@ 'use strict';

*/
module.exports = provider => function* checkClient(next) {
const clientId = this.oidc.params.client_id;
this.assert(clientId, new errors.InvalidRequestError('missing required parameter client_id'));
module.exports = provider => async function checkClient(ctx, next) {
const clientId = ctx.oidc.params.client_id;
ctx.assert(clientId, new errors.InvalidRequestError('missing required parameter client_id'));
const Client = provider.Client;
const client = yield Client.find(String(clientId));
const client = await Client.find(String(clientId));
this.assert(client, new errors.InvalidClientError());
ctx.assert(client, new errors.InvalidClientError());
this.oidc.client = client;
ctx.oidc.client = client;
yield next;
await next();
};

@@ -10,9 +10,9 @@ 'use strict';

*/
module.exports = function* checkOpenIdPresent(next) {
const scopes = this.oidc.params.scope.split(' ');
module.exports = async function checkOpenIdPresent(ctx, next) {
const scopes = ctx.oidc.params.scope.split(' ');
this.assert(scopes.indexOf('openid') !== -1,
ctx.assert(scopes.indexOf('openid') !== -1,
new errors.InvalidRequestError('openid is required scope'));
yield next;
await next();
};

@@ -11,10 +11,10 @@ 'use strict';

*/
module.exports = function* checkPixy(next) {
const params = this.oidc.params;
module.exports = async function checkPixy(ctx, next) {
const params = ctx.oidc.params;
if (params.code_challenge_method) {
this.assert(ALLOWED.indexOf(params.code_challenge_method) !== -1,
ctx.assert(ALLOWED.indexOf(params.code_challenge_method) !== -1,
new errors.InvalidRequestError('not supported value of code_challenge_method'));
this.assert(params.code_challenge,
ctx.assert(params.code_challenge,
new errors.InvalidRequestError('code_challenge must be provided with code_challenge_method'));

@@ -27,3 +27,3 @@ }

yield next;
await next();
};

@@ -13,15 +13,15 @@ 'use strict';

*/
module.exports = provider => function* checkPrompt(next) {
if (this.oidc.params.prompt !== undefined) {
const prompts = this.oidc.prompts;
module.exports = provider => async function checkPrompt(ctx, next) {
if (ctx.oidc.params.prompt !== undefined) {
const prompts = ctx.oidc.prompts;
const unsupported = _.difference(prompts, instance(provider).configuration('prompts'));
this.assert(_.isEmpty(unsupported), new errors.InvalidRequestError(
ctx.assert(_.isEmpty(unsupported), new errors.InvalidRequestError(
`invalid prompt value(s) provided. (${unsupported.join(',')})`));
this.assert(prompts.indexOf('none') === -1 || prompts.length === 1,
ctx.assert(prompts.indexOf('none') === -1 || prompts.length === 1,
new errors.InvalidRequestError('prompt none must only be used alone'));
}
yield next;
await next();
};

@@ -10,8 +10,8 @@ 'use strict';

*/
module.exports = function* checkRedirectUri(next) {
this.oidc.redirectUriCheckPerformed = true;
this.assert(this.oidc.client.redirectUriAllowed(this.oidc.params.redirect_uri),
module.exports = async function checkRedirectUri(ctx, next) {
ctx.oidc.redirectUriCheckPerformed = true;
ctx.assert(ctx.oidc.client.redirectUriAllowed(ctx.oidc.params.redirect_uri),
new errors.RedirectUriMismatchError());
yield next;
await next();
};

@@ -22,4 +22,4 @@ 'use strict';

*/
module.exports = function* checkResponseMode(next) {
const params = this.oidc.params;
module.exports = async function checkResponseMode(ctx, next) {
const params = ctx.oidc.params;

@@ -31,3 +31,3 @@ if (params.response_mode === undefined) {

this.assert(!invalid, new errors.InvalidRequestError(
ctx.assert(!invalid, new errors.InvalidRequestError(
'response_mode not allowed for this response_type'));

@@ -37,3 +37,3 @@ }

yield next;
await next();
};

@@ -12,12 +12,12 @@ 'use strict';

*/
module.exports = provider => function* checkResponseType(next) {
const params = this.oidc.params;
module.exports = provider => async function checkResponseType(ctx, next) {
const params = ctx.oidc.params;
const supported = instance(provider).configuration('responseTypes');
const valid = supported.indexOf(params.response_type) !== -1;
this.assert(valid, 400, 'unsupported_response_type', {
ctx.assert(valid, 400, 'unsupported_response_type', {
error_description: `response_type not supported. (${params.response_type})`,
});
this.assert(this.oidc.client.responseTypeAllowed(params.response_type),
ctx.assert(ctx.oidc.client.responseTypeAllowed(params.response_type),
400, 'restricted_response_type', {

@@ -27,3 +27,3 @@ error_description: 'response_type not allowed for this client',

yield next;
await next();
};

@@ -12,12 +12,12 @@ 'use strict';

*/
module.exports = provider => function* checkScope(next) {
const scopes = this.oidc.params.scope.split(' ');
const responseType = this.oidc.params.response_type;
const prompts = this.oidc.prompts;
module.exports = provider => async function checkScope(ctx, next) {
const scopes = ctx.oidc.params.scope.split(' ');
const responseType = ctx.oidc.params.response_type;
const prompts = ctx.oidc.prompts;
const unsupported = _.difference(scopes, instance(provider).configuration('scopes'));
this.assert(_.isEmpty(unsupported), new errors.InvalidRequestError(
ctx.assert(_.isEmpty(unsupported), new errors.InvalidRequestError(
`invalid scope value(s) provided. (${unsupported.join(',')})`));
this.assert(scopes.indexOf('openid') !== -1,
ctx.assert(scopes.indexOf('openid') !== -1,
new errors.InvalidRequestError('openid is required scope'));

@@ -35,6 +35,6 @@

if (responseType.includes('code')) {
this.assert(prompts.indexOf('consent') !== -1,
ctx.assert(prompts.indexOf('consent') !== -1,
new errors.InvalidRequestError('offline_access scope requires consent prompt'));
} else {
this.oidc.params.scope = _.pull(scopes, 'offline_access').join(' ');
ctx.oidc.params.scope = _.pull(scopes, 'offline_access').join(' ');
}

@@ -44,3 +44,3 @@ }

yield next;
await next();
};

@@ -14,7 +14,7 @@ 'use strict';

*/
module.exports = provider => function* decodeRequest(next) {
const params = this.oidc.params;
module.exports = provider => async function decodeRequest(ctx, next) {
const params = ctx.oidc.params;
if (params.request === undefined) {
yield next;
await next();
return;

@@ -28,3 +28,3 @@ }

params.request.split('.').length === 5) {
const decrypted = yield JWT.decrypt(params.request, instance(provider).keystore);
const decrypted = await JWT.decrypt(params.request, instance(provider).keystore);
params.request = decrypted.payload.toString('utf8');

@@ -34,3 +34,3 @@ }

} catch (err) {
this.throw(400, 'invalid_request_object', {
ctx.throw(400, 'invalid_request_object', {
error_description: `could not parse request_uri as valid JWT (${err.message})`,

@@ -42,3 +42,3 @@ });

this.assert(payload.request === undefined &&
ctx.assert(payload.request === undefined &&
payload.request_uri === undefined, 400, 'invalid_request_object', {

@@ -50,3 +50,3 @@ error_description: 'request object must not contain request or request_uri properties',

this.assert(payload.response_type === undefined ||
ctx.assert(payload.response_type === undefined ||
payload.response_type === params.response_type, 400,

@@ -57,3 +57,3 @@ 'invalid_request_object', {

this.assert(payload.client_id === undefined ||
ctx.assert(payload.client_id === undefined ||
payload.client_id === params.client_id, 400, 'invalid_request_object', {

@@ -63,7 +63,7 @@ error_description: 'request client_id must equal the one in request parameters',

const client = this.oidc.client;
const client = ctx.oidc.client;
const alg = decoded.header.alg;
if (client.requestObjectSigningAlg) {
this.assert(client.requestObjectSigningAlg === alg, 400,
ctx.assert(client.requestObjectSigningAlg === alg, 400,
'invalid_request_object', {

@@ -76,5 +76,5 @@ error_description: 'the preregistered alg must be used in request or request_uri',

try {
yield JWT.verify(params.request, client.keystore);
await JWT.verify(params.request, client.keystore);
} catch (err) {
this.throw(400, 'invalid_request_object', {
ctx.throw(400, 'invalid_request_object', {
error_description: `could not validate request object signature (${err.message})`,

@@ -88,3 +88,3 @@ });

yield next;
await next();
};

@@ -18,14 +18,14 @@ 'use strict';

return function* fetchRequestUri(next) {
const params = this.oidc.params;
return async function fetchRequestUri(ctx, next) {
const params = ctx.oidc.params;
if (params.request_uri !== undefined) {
this.assert(params.request_uri.length <= 512, 400, 'invalid_request_uri', {
ctx.assert(params.request_uri.length <= 512, 400, 'invalid_request_uri', {
error_description: 'the request_uri MUST NOT exceed 512 characters' });
this.assert(params.request_uri.startsWith('https://'), 400,
ctx.assert(params.request_uri.startsWith('https://'), 400,
'invalid_request_uri', { error_description: 'request_uri must use https scheme' });
if (this.oidc.client.requestUris) {
this.assert(this.oidc.client.requestUriAllowed(params.request_uri), 400,
if (ctx.oidc.client.requestUris) {
ctx.assert(ctx.oidc.client.requestUriAllowed(params.request_uri), 400,
'invalid_request_uri', { error_description: 'not registered request_uri provided' });

@@ -35,6 +35,6 @@ }

try {
params.request = yield cache.resolve(params.request_uri);
params.request = await cache.resolve(params.request_uri);
params.request_uri = undefined;
} catch (err) {
this.throw(400, 'invalid_request_uri', {
ctx.throw(400, 'invalid_request_uri', {
error_description: `could not load or parse request_uri (${err.message})` });

@@ -44,4 +44,4 @@ }

yield next;
await next();
};
};

@@ -14,5 +14,4 @@ 'use strict';

return function* interactions(next) {
const ctx = this.oidc;
const clientName = _.get(ctx.client, 'name', 'Client');
return async function interactions(ctx, next) {
const clientName = _.get(ctx.oidc.client, 'name', 'Client');

@@ -23,3 +22,3 @@ const interactionChecks = [

() => {
if (!ctx.session.accountId()) {
if (!ctx.oidc.session.accountId()) {
return {

@@ -37,3 +36,3 @@ error: 'login_required',

() => {
if (ctx.prompted('login')) {
if (ctx.oidc.prompted('login')) {
return {

@@ -51,3 +50,3 @@ error: 'login_required',

() => {
if (ctx.session.past(ctx.params.max_age)) {
if (ctx.oidc.session.past(ctx.oidc.params.max_age)) {
return {

@@ -65,5 +64,5 @@ error: 'login_required',

() => {
if (_.has(ctx.claims, 'id_token.sub.value')) {
const subject = Claims.sub(ctx.session.accountId(), ctx.client.sectorIdentifier);
if (ctx.claims.id_token.sub.value !== subject) {
if (_.has(ctx.oidc.claims, 'id_token.sub.value')) {
const subject = Claims.sub(ctx.oidc.session.accountId(), ctx.oidc.client.sectorIdentifier); // eslint-disable-line max-len
if (ctx.oidc.claims.id_token.sub.value !== subject) {
return {

@@ -84,5 +83,5 @@ error: 'login_required',

() => {
const request = _.get(ctx.claims, 'id_token.acr', {});
const request = _.get(ctx.oidc.claims, 'id_token.acr', {});
if (request && request.essential && request.values) {
if (request.values.indexOf(ctx.acr) === -1) {
if (request.values.indexOf(ctx.oidc.acr) === -1) {
return {

@@ -101,5 +100,5 @@ error: 'login_required',

() => {
const request = _.get(ctx.claims, 'id_token.acr', {});
const request = _.get(ctx.oidc.claims, 'id_token.acr', {});
if (request && request.essential && request.value) {
if (request.value !== ctx.acr) {
if (request.value !== ctx.oidc.acr) {
return {

@@ -118,4 +117,4 @@ error: 'login_required',

() => {
const missed = _.find(ctx.prompts, (prompt) => {
if (prompt !== 'none' && ctx.prompted(prompt)) {
const missed = _.find(ctx.oidc.prompts, (prompt) => {
if (prompt !== 'none' && ctx.oidc.prompted(prompt)) {
return true;

@@ -143,3 +142,3 @@ }

() => {
if (!ctx.session.sidFor(ctx.client.clientId)) {
if (!ctx.oidc.session.sidFor(ctx.oidc.client.clientId)) {
return {

@@ -156,7 +155,7 @@ error: 'consent_required',

() => {
if (ctx.params.id_token_hint !== undefined) {
const actualSub = Claims.sub(ctx.session.accountId(), ctx.client.sectorIdentifier);
if (ctx.oidc.params.id_token_hint !== undefined) {
const actualSub = Claims.sub(ctx.oidc.session.accountId(), ctx.oidc.client.sectorIdentifier); // eslint-disable-line max-len
const IdToken = provider.IdToken;
return IdToken.validate(ctx.params.id_token_hint, ctx.client).then((decoded) => {
return IdToken.validate(ctx.oidc.params.id_token_hint, ctx.oidc.client).then((decoded) => { // eslint-disable-line max-len
if (decoded.payload.sub !== actualSub) {

@@ -186,3 +185,3 @@ return {

interaction = fn();
if (interaction instanceof Promise) interaction = yield interaction;
if (interaction instanceof Promise) interaction = await interaction;
if (interaction) break;

@@ -198,26 +197,26 @@ }

// if interaction needed but prompt=none => throw;
this.assert(!ctx.prompted('none'), 302, interaction.error, {
ctx.assert(!ctx.oidc.prompted('none'), 302, interaction.error, {
error_description: interaction.error_description,
});
const destination = instance(provider).configuration('interactionUrl').call(this, interaction);
const destination = instance(provider).configuration('interactionUrl').call(ctx, interaction);
const cookieOptions = instance(provider).configuration('cookies.short');
this.cookies.set('_grant', j({
ctx.cookies.set('_grant', j({
interaction,
uuid: ctx.uuid,
returnTo: ctx.urlFor('resume', { grant: ctx.uuid }),
params: ctx.params,
uuid: ctx.oidc.uuid,
returnTo: ctx.oidc.urlFor('resume', { grant: ctx.oidc.uuid }),
params: ctx.oidc.params,
}), Object.assign({ path: url.parse(destination).pathname }, cookieOptions));
this.cookies.set('_grant', j(ctx.params), Object.assign({
path: provider.pathFor('resume', { grant: ctx.uuid }),
ctx.cookies.set('_grant', j(ctx.oidc.params), Object.assign({
path: provider.pathFor('resume', { grant: ctx.oidc.uuid }),
}, cookieOptions));
provider.emit('interaction.started', interaction, this);
return this.redirect(destination);
provider.emit('interaction.started', interaction, ctx);
return ctx.redirect(destination);
}
return yield next;
return await next();
};
};

@@ -6,11 +6,11 @@ 'use strict';

*/
module.exports = provider => function* loadAccount(next) {
const accountId = this.oidc.session.accountId();
module.exports = provider => async function loadAccount(ctx, next) {
const accountId = ctx.oidc.session.accountId();
if (accountId) {
const Account = provider.Account;
this.oidc.account = yield Account.findById(accountId);
ctx.oidc.account = await Account.findById(accountId);
}
yield next;
await next();
};

@@ -7,4 +7,4 @@ 'use strict';

*/
module.exports = function* noRedirectUriClients(next) {
const oidc = this.oidc;
module.exports = async function noRedirectUriClients(ctx, next) {
const oidc = ctx.oidc;

@@ -15,3 +15,3 @@ if (oidc.params.redirect_uri === undefined && oidc.client.redirectUris.length === 1) {

yield next;
await next();
};

@@ -11,5 +11,5 @@ 'use strict';

*/
module.exports = function* oauthRequired(next) {
module.exports = async function oauthRequired(ctx, next) {
// Validate: required oauth params
const params = this.oidc.params;
const params = ctx.oidc.params;
const missing = _.difference([

@@ -21,6 +21,6 @@ 'response_type',

this.assert(_.isEmpty(missing), new errors.InvalidRequestError(
ctx.assert(_.isEmpty(missing), new errors.InvalidRequestError(
`missing required parameter(s) ${missing.join(',')}`));
yield next;
await next();
};

@@ -12,5 +12,5 @@ 'use strict';

*/
module.exports = function* oidcRequired(next) {
module.exports = async function oidcRequired(ctx, next) {
// Validate: required params
const params = this.oidc.params;
const params = ctx.oidc.params;
const missing = [];

@@ -25,6 +25,6 @@

this.assert(_.isEmpty(missing), new errors.InvalidRequestError(
ctx.assert(_.isEmpty(missing), new errors.InvalidRequestError(
`missing required parameter(s) ${missing.join(',')}`));
yield next;
await next();
};

@@ -12,3 +12,3 @@ 'use strict';

function* tokenHandler() {
async function tokenHandler() {
const at = new AccessToken({

@@ -24,3 +24,3 @@ accountId: this.oidc.session.accountId(),

return {
access_token: yield at.save(),
access_token: await at.save(),
expires_in: AccessToken.expiresIn,

@@ -31,3 +31,3 @@ token_type: 'Bearer',

function* codeHandler() {
async function codeHandler() {
const ac = new AuthorizationCode({

@@ -52,8 +52,8 @@ accountId: this.oidc.session.accountId(),

return { code: yield ac.save() };
return { code: await ac.save() };
}
function* idTokenHandler() {
async function idTokenHandler() {
const token = new IdToken(
Object.assign({}, yield Promise.resolve(this.oidc.account.claims()), {
Object.assign({}, await Promise.resolve(this.oidc.account.claims()), {
acr: this.oidc.acr,

@@ -100,5 +100,5 @@ amr: this.oidc.amr,

*/
return function* processResponseTypes() {
const responses = this.oidc.params.response_type.split(' ');
const out = Object.assign.apply({}, yield responses.map(callHandlers.bind(this)));
return async function processResponseTypes(ctx) {
const responses = ctx.oidc.params.response_type.split(' ');
const out = Object.assign.apply({}, await Promise.all(responses.map(callHandlers.bind(ctx))));

@@ -114,3 +114,3 @@ if (out.access_token && out.id_token) {

if (out.id_token) {
out.id_token = yield out.id_token.sign(this.oidc.client);
out.id_token = await out.id_token.sign(ctx.oidc.client);
}

@@ -117,0 +117,0 @@

@@ -27,17 +27,17 @@ 'use strict';

*/
module.exports = provider => function* respond(next) {
const out = yield next;
module.exports = provider => async function respond(ctx, next) {
const out = await next();
if (this.oidc.params.state !== undefined) out.state = this.oidc.params.state;
if (ctx.oidc.params.state !== undefined) out.state = ctx.oidc.params.state;
provider.emit('authorization.success', this);
provider.emit('authorization.success', ctx);
if (instance(provider).configuration('features.sessionManagement')) {
const salt = crypto.randomBytes(8).toString('hex');
const state = String(this.oidc.session.authTime());
const state = String(ctx.oidc.session.authTime());
const shasum = crypto.createHash('sha256')
.update(this.oidc.params.client_id)
.update(ctx.oidc.params.client_id)
.update(' ')
.update(locationOrigin(this.oidc.params.redirect_uri))
.update(locationOrigin(ctx.oidc.params.redirect_uri))
.update(' ')

@@ -50,4 +50,4 @@ .update(state)

const stateCookieName = `_state.${this.oidc.params.client_id}`;
this.cookies.set(stateCookieName, state,
const stateCookieName = `_state.${ctx.oidc.params.client_id}`;
ctx.cookies.set(stateCookieName, state,
Object.assign({}, instance(provider).configuration('cookies.long'), { httpOnly: false }));

@@ -58,11 +58,11 @@

if (instance(provider).responseModes.has(this.oidc.params.response_mode)) {
instance(provider).responseModes.get(this.oidc.params.response_mode)
.call(this, this.oidc.params.redirect_uri, out);
} else if (this.oidc.params.response_mode === 'form_post') {
formPost.call(this, this.oidc.params.redirect_uri, out);
if (instance(provider).responseModes.has(ctx.oidc.params.response_mode)) {
instance(provider).responseModes.get(ctx.oidc.params.response_mode)
.call(ctx, ctx.oidc.params.redirect_uri, out);
} else if (ctx.oidc.params.response_mode === 'form_post') {
formPost.call(ctx, ctx.oidc.params.redirect_uri, out);
} else {
const uri = redirectUri(this.oidc.params.redirect_uri, out, this.oidc.params.response_mode);
this.redirect(uri);
const uri = redirectUri(ctx.oidc.params.redirect_uri, out, ctx.oidc.params.response_mode);
ctx.redirect(uri);
}
};

@@ -15,8 +15,8 @@ 'use strict';

*/
module.exports = provider => function* throwNotSupported(next) {
const params = this.oidc.params;
module.exports = provider => async function throwNotSupported(ctx, next) {
const params = ctx.oidc.params;
const feature = instance(provider).configuration('features');
if (!feature.request && params.request !== undefined) {
this.throw(400, 'request_not_supported', {
ctx.throw(400, 'request_not_supported', {
error_description: 'request parameter provided but not supported',

@@ -27,3 +27,3 @@ });

if (!feature.requestUri && params.request_uri !== undefined) {
this.throw(400, 'request_uri_not_supported', {
ctx.throw(400, 'request_uri_not_supported', {
error_description: 'request_uri parameter provided but not supported',

@@ -34,3 +34,3 @@ });

if (params.registration !== undefined) {
this.throw(400, 'registration_not_supported', {
ctx.throw(400, 'registration_not_supported', {
error_description: 'registration parameter provided but not supported',

@@ -40,7 +40,7 @@ });

this.assert(params.request === undefined ||
ctx.assert(params.request === undefined ||
params.request_uri === undefined, new errors.InvalidRequestError(
'request and request_uri parameters MUST NOT be used together'));
yield next;
await next();
};

@@ -6,7 +6,7 @@ 'use strict';

module.exports = function certificatesAction(provider) {
return function* renderCertificates(next) {
this.body = instance(provider).keystore.toJSON();
return async function renderCertificates(ctx, next) {
ctx.body = instance(provider).keystore.toJSON();
yield next;
await next();
};
};
'use strict';
module.exports = function checkSessionAction() {
return function* checkSessionIframe(next) {
const debug = this.query.debug !== undefined;
this.type = 'html';
this.body = `<!DOCTYPE html>
return async function checkSessionIframe(ctx, next) {
const debug = ctx.query.debug !== undefined;
ctx.type = 'html';
ctx.body = `<!DOCTYPE html>
<html>

@@ -69,4 +69,4 @@ <head lang="en">

</html>`;
yield next;
await next();
};
};

@@ -9,6 +9,6 @@ 'use strict';

return function* renderConfiguration(next) {
this.body = {
return async function renderConfiguration(ctx, next) {
ctx.body = {
acr_values_supported: config.acrValues.length ? config.acrValues : undefined,
authorization_endpoint: this.oidc.urlFor('authorization'),
authorization_endpoint: ctx.oidc.urlFor('authorization'),
claims_parameter_supported: !!config.features.claimsParameter,

@@ -19,5 +19,5 @@ claims_supported: config.claimsSupported,

issuer: provider.issuer,
jwks_uri: this.oidc.urlFor('certificates'),
jwks_uri: ctx.oidc.urlFor('certificates'),
registration_endpoint: config.features.registration ?
this.oidc.urlFor('registration') : undefined,
ctx.oidc.urlFor('registration') : undefined,
request_object_signing_alg_values_supported:

@@ -38,10 +38,10 @@ config.features.request || config.features.requestUri ?

subject_types_supported: config.subjectTypes,
token_endpoint: this.oidc.urlFor('token'),
token_endpoint: ctx.oidc.urlFor('token'),
token_endpoint_auth_methods_supported: config.tokenEndpointAuthMethods,
token_endpoint_auth_signing_alg_values_supported: config.tokenEndpointAuthSigningAlgValues,
token_introspection_endpoint: config.features.introspection ?
this.oidc.urlFor('introspection') : undefined,
ctx.oidc.urlFor('introspection') : undefined,
token_revocation_endpoint: config.features.revocation ?
this.oidc.urlFor('revocation') : undefined,
userinfo_endpoint: this.oidc.urlFor('userinfo'),
ctx.oidc.urlFor('revocation') : undefined,
userinfo_endpoint: ctx.oidc.urlFor('userinfo'),
userinfo_signing_alg_values_supported: config.userinfoSigningAlgValues,

@@ -51,11 +51,11 @@ };

if (config.features.encryption) {
this.body.id_token_encryption_alg_values_supported = config.idTokenEncryptionAlgValues;
this.body.id_token_encryption_enc_values_supported = config.idTokenEncryptionEncValues;
this.body.userinfo_encryption_alg_values_supported = config.userinfoEncryptionAlgValues;
this.body.userinfo_encryption_enc_values_supported = config.userinfoEncryptionEncValues;
ctx.body.id_token_encryption_alg_values_supported = config.idTokenEncryptionAlgValues;
ctx.body.id_token_encryption_enc_values_supported = config.idTokenEncryptionEncValues;
ctx.body.userinfo_encryption_alg_values_supported = config.userinfoEncryptionAlgValues;
ctx.body.userinfo_encryption_enc_values_supported = config.userinfoEncryptionEncValues;
if (config.features.request || config.features.requestUri) {
this.body.request_object_encryption_alg_values_supported =
ctx.body.request_object_encryption_alg_values_supported =
config.requestObjectEncryptionAlgValues;
this.body.request_object_encryption_enc_values_supported =
ctx.body.request_object_encryption_enc_values_supported =
config.requestObjectEncryptionEncValues;

@@ -66,15 +66,15 @@ }

if (config.features.sessionManagement) {
this.body.check_session_iframe = this.oidc.urlFor('check_session');
this.body.end_session_endpoint = this.oidc.urlFor('end_session');
ctx.body.check_session_iframe = ctx.oidc.urlFor('check_session');
ctx.body.end_session_endpoint = ctx.oidc.urlFor('end_session');
if (config.features.backchannelLogout) {
this.body.backchannel_logout_supported = true;
this.body.backchannel_logout_session_supported = true;
ctx.body.backchannel_logout_supported = true;
ctx.body.backchannel_logout_session_supported = true;
}
}
_.defaults(this.body, config.discovery);
_.defaults(ctx.body, config.discovery);
yield next;
await next();
};
};

@@ -20,5 +20,5 @@ 'use strict';

module.exports = function endSessionAction(provider) {
const loadClient = function* loadClient(clientId) {
async function loadClient(clientId) {
// Validate: client_id param
const client = yield provider.Client.find(clientId);
const client = await provider.Client.find(clientId);

@@ -28,3 +28,3 @@ this.assert(client, new errors.InvalidClientError('unrecognized azp or aud claims'));

return client;
};
}

@@ -37,4 +37,4 @@ return {

function* endSessionChecks(next) {
const params = this.oidc.params;
async function endSessionChecks(ctx, next) {
const params = ctx.oidc.params;

@@ -49,3 +49,3 @@ if (params.id_token_hint) {

} catch (err) {
return this.throw(new errors.InvalidRequestError(
return ctx.throw(new errors.InvalidRequestError(
`could not decode id_token_hint (${err.message})`));

@@ -56,6 +56,6 @@ }

try {
client = yield loadClient.call(this, clientId);
yield provider.IdToken.validate(params.id_token_hint, client);
client = await loadClient.call(ctx, clientId);
await provider.IdToken.validate(params.id_token_hint, client);
} catch (err) {
this.throw(new errors.InvalidRequestError(
ctx.throw(new errors.InvalidRequestError(
`could not validate id_token_hint (${err.message})`));

@@ -65,7 +65,7 @@ }

if (params.post_logout_redirect_uri) {
this.assert(client.postLogoutRedirectUriAllowed(params.post_logout_redirect_uri),
ctx.assert(client.postLogoutRedirectUriAllowed(params.post_logout_redirect_uri),
new errors.InvalidRequestError('post_logout_redirect_uri not registered'));
}
this.oidc.client = client;
ctx.oidc.client = client;
} else {

@@ -75,22 +75,22 @@ params.post_logout_redirect_uri = undefined;

yield next;
await next();
},
function* renderLogout(next) {
async function renderLogout(ctx, next) {
const secret = crypto.randomBytes(24).toString('hex');
this.oidc.session.logout = {
ctx.oidc.session.logout = {
secret,
clientId: this.oidc.client ? this.oidc.client.clientId : undefined,
postLogoutRedirectUri: this.oidc.params.post_logout_redirect_uri ||
clientId: ctx.oidc.client ? ctx.oidc.client.clientId : undefined,
postLogoutRedirectUri: ctx.oidc.params.post_logout_redirect_uri ||
instance(provider).configuration('postLogoutRedirectUri'),
};
this.type = 'html';
this.status = 200;
ctx.type = 'html';
ctx.status = 200;
const formhtml = `<form id="op.logoutForm" method="post" action="${provider.pathFor('end_session')}"><input type="hidden" name="xsrf" value="${secret}"/></form>`;
instance(provider).configuration('logoutSource').call(this, formhtml);
instance(provider).configuration('logoutSource').call(ctx, formhtml);
yield next;
await next();
},

@@ -106,25 +106,25 @@ ]),

function* checkLogoutToken(next) {
this.assert(this.oidc.session.logout, new errors.InvalidRequestError(
async function checkLogoutToken(ctx, next) {
ctx.assert(ctx.oidc.session.logout, new errors.InvalidRequestError(
'could not find logout details'));
this.assert(this.oidc.session.logout.secret === this.oidc.params.xsrf,
ctx.assert(ctx.oidc.session.logout.secret === ctx.oidc.params.xsrf,
new errors.InvalidRequestError('xsrf token invalid'));
yield next;
await next();
},
function* endSession(next) {
const params = this.oidc.session.logout;
async function endSession(ctx, next) {
const params = ctx.oidc.session.logout;
const cookieOpts = _.omit(instance(provider).configuration('cookies.long'), 'maxAge', 'signed');
if (this.oidc.params.logout) {
if (ctx.oidc.params.logout) {
if (instance(provider).configuration('features.backchannelLogout')) {
try {
const Client = provider.Client;
const clientIds = Object.keys(this.oidc.session.authorizations);
const clientIds = Object.keys(ctx.oidc.session.authorizations);
const logouts = clientIds.map(visitedClientId => Client.find(visitedClientId)
.then((visitedClient) => {
if (visitedClient && visitedClient.backchannelLogoutUri) {
return visitedClient.backchannelLogout(this.oidc.session.accountId(),
this.oidc.session.sidFor(visitedClient.clientId));
return visitedClient.backchannelLogout(ctx.oidc.session.accountId(),
ctx.oidc.session.sidFor(visitedClient.clientId));
}

@@ -134,18 +134,18 @@ return undefined;

yield logouts;
await Promise.all(logouts);
} catch (err) {}
}
yield this.oidc.session.destroy();
await ctx.oidc.session.destroy();
// get all cookies matching _state.[clientId](.sig) and drop them
this.get('cookie').match(STATES).forEach(val => this.cookies.set(val.slice(0, -1), null,
ctx.get('cookie').match(STATES).forEach(val => ctx.cookies.set(val.slice(0, -1), null,
cookieOpts));
this.cookies.set('_session', null, cookieOpts);
this.cookies.set('_session.sig', null, cookieOpts);
ctx.cookies.set('_session', null, cookieOpts);
ctx.cookies.set('_session.sig', null, cookieOpts);
} else if (params.clientId) {
delete this.oidc.session.authorizations[params.clientId];
this.cookies.set(`_state.${params.clientId}`, null, cookieOpts);
this.cookies.set(`_state.${params.clientId}.sig`, null, cookieOpts);
delete ctx.oidc.session.authorizations[params.clientId];
ctx.cookies.set(`_state.${params.clientId}`, null, cookieOpts);
ctx.cookies.set(`_state.${params.clientId}.sig`, null, cookieOpts);
}

@@ -156,5 +156,5 @@

this.redirect(uri);
ctx.redirect(uri);
yield next;
await next();
},

@@ -161,0 +161,0 @@ ]),

@@ -10,13 +10,13 @@ 'use strict';

function* parseCookie(next) {
const cookie = this.cookies.get('_grant');
this.assert(cookie, 400);
async function parseCookie(ctx, next) {
const cookie = ctx.cookies.get('_grant');
ctx.assert(cookie, 400);
const fads = JSON.parse(cookie);
this.uuid = this.params.grant;
ctx.uuid = ctx.params.grant;
['interaction', 'params', 'returnTo'].forEach((detail) => {
Object.defineProperty(this, detail, { get() { return fads[detail]; } });
Object.defineProperty(ctx, detail, { get() { return fads[detail]; } });
});
yield next;
await next();
}

@@ -34,9 +34,9 @@

parseCookie,
function* interactionRender() {
const client = yield provider.Client.find(this.params.client_id);
this.assert(client, 400);
async function interactionRender(ctx, next) {
const client = await provider.Client.find(ctx.params.client_id);
ctx.assert(client, 400);
const action = router.url('interaction', { grant: this.uuid });
const action = router.url('interaction', { grant: ctx.uuid });
const view = (() => {
switch (this.interaction.reason) {
switch (ctx.interaction.reason) {
case 'consent_prompt':

@@ -49,13 +49,14 @@ case 'client_not_authorized':

})();
const locals = {
action,
client,
returnTo: this.returnTo,
params: this.params,
returnTo: ctx.returnTo,
params: ctx.params,
};
locals.body = views[view](locals);
this.type = 'html';
this.body = views.layout(locals);
ctx.type = 'html';
ctx.body = views.layout(locals);
await next();
},

@@ -66,10 +67,10 @@ ]),

parseCookie,
function* interactionSubmit(next) {
switch (this.request.body.view) { // eslint-disable-line default-case
async function interactionSubmit(ctx, next) {
switch (ctx.request.body.view) { // eslint-disable-line default-case
case 'login':
provider.resume(this, this.uuid, {
provider.resume(ctx, ctx.uuid, {
login: {
account: this.request.body.login,
account: ctx.request.body.login,
acr: '1',
remember: !!this.request.body.remember,
remember: !!ctx.request.body.remember,
ts: Math.floor(Date.now() / 1000),

@@ -81,7 +82,7 @@ },

case 'interaction':
provider.resume(this, this.uuid, { consent: {} });
provider.resume(ctx, ctx.uuid, { consent: {} });
break;
}
yield next;
await next();
},

@@ -88,0 +89,0 @@ ]),

@@ -44,12 +44,12 @@ 'use strict';

function* validateTokenPresence(next) {
presence.call(this, ['token']);
yield next;
async function validateTokenPresence(ctx, next) {
presence.call(ctx, ['token']);
await next();
},
function* renderTokenResponse(next) {
async function renderTokenResponse(ctx, next) {
let token;
const params = this.oidc.params;
const params = ctx.oidc.params;
this.body = { active: false };
ctx.body = { active: false };

@@ -98,13 +98,13 @@ let tryhard;

try {
token = yield tryhard;
token = await tryhard;
switch (token && token.kind) {
case 'AccessToken':
this.body.token_type = 'access_token';
ctx.body.token_type = 'access_token';
break;
case 'ClientCredentials':
this.body.token_type = 'client_credentials';
ctx.body.token_type = 'client_credentials';
break;
case 'RefreshToken':
this.body.token_type = 'refresh_token';
ctx.body.token_type = 'refresh_token';
break;

@@ -116,14 +116,14 @@ default:

if (!this.body.token_type) {
if (!ctx.body.token_type) {
return;
}
if (token.clientId !== this.oidc.client.clientId) {
this.body.sub = Claims.sub(token.accountId,
(yield provider.Client.find(token.clientId)).sectorIdentifier);
if (token.clientId !== ctx.oidc.client.clientId) {
ctx.body.sub = Claims.sub(token.accountId,
(await provider.Client.find(token.clientId)).sectorIdentifier);
} else {
this.body.sub = Claims.sub(token.accountId, this.oidc.client.sectorIdentifier);
ctx.body.sub = Claims.sub(token.accountId, ctx.oidc.client.sectorIdentifier);
}
Object.assign(this.body, {
Object.assign(ctx.body, {
active: token.isValid,

@@ -139,5 +139,5 @@ client_id: token.clientId,

yield next;
await next();
},
]);
};

@@ -30,8 +30,8 @@ 'use strict';

module.exports = function registrationAction(provider) {
function* validateInitialAccessToken(next) {
async function validateInitialAccessToken(ctx, next) {
const setup = instance(provider).configuration('features.registration');
switch (setup.initialAccessToken && typeof setup.initialAccessToken) {
case 'boolean': {
const initialAccessToken = yield provider.InitialAccessToken.find(this.oidc.bearer);
this.assert(initialAccessToken, new errors.InvalidTokenError());
const initialAccessToken = await provider.InitialAccessToken.find(ctx.oidc.bearer);
ctx.assert(initialAccessToken, new errors.InvalidTokenError());
break;

@@ -42,5 +42,5 @@ }

new Buffer(setup.initialAccessToken, 'utf8'),
new Buffer(this.oidc.bearer, 'utf8'),
new Buffer(ctx.oidc.bearer, 'utf8'),
1000);
this.assert(valid, new errors.InvalidTokenError());
ctx.assert(valid, new errors.InvalidTokenError());
break;

@@ -51,19 +51,19 @@ }

yield next;
await next();
}
function* validateRegistrationAccessToken(next) {
const regAccessToken = yield provider.RegistrationAccessToken.find(this.oidc.bearer);
this.assert(regAccessToken, new errors.InvalidTokenError());
async function validateRegistrationAccessToken(ctx, next) {
const regAccessToken = await provider.RegistrationAccessToken.find(ctx.oidc.bearer);
ctx.assert(regAccessToken, new errors.InvalidTokenError());
const client = yield provider.Client.find(this.params.clientId);
const client = await provider.Client.find(ctx.params.clientId);
if (!client || client.clientId !== regAccessToken.clientId) {
yield regAccessToken.destroy();
this.throw(new errors.InvalidTokenError());
await regAccessToken.destroy();
ctx.throw(new errors.InvalidTokenError());
}
this.oidc.client = client;
ctx.oidc.client = client;
yield next;
await next();
}

@@ -76,3 +76,3 @@

validateInitialAccessToken,
function* registrationResponse() {
async function registrationResponse(ctx, next) {
const properties = {};

@@ -83,3 +83,3 @@ const clientId = uuid.v4();

Object.assign(properties, this.request.body, {
Object.assign(properties, ctx.request.body, {
client_id: clientId,

@@ -98,16 +98,18 @@ client_id_issued_at: epochTime(),

const client = yield instance(provider).clientAdd(properties, true);
const client = await instance(provider).clientAdd(properties, true);
this.body = client.metadata();
ctx.body = client.metadata();
Object.assign(this.body, {
registration_client_uri: this.oidc.urlFor('registration_client', {
Object.assign(ctx.body, {
registration_client_uri: ctx.oidc.urlFor('registration_client', {
clientId: properties.client_id,
}),
registration_access_token: yield rat.save(),
registration_access_token: await rat.save(),
});
this.status = 201;
ctx.status = 201;
provider.emit('registration_create.success', client, this);
provider.emit('registration_create.success', client, ctx);
await next();
},

@@ -120,13 +122,13 @@ ]),

function* clientReadResponse(next) {
this.body = this.oidc.client.metadata();
async function clientReadResponse(ctx, next) {
ctx.body = ctx.oidc.client.metadata();
Object.assign(this.body, {
registration_access_token: this.oidc.bearer,
registration_client_uri: this.oidc.urlFor('registration_client', {
clientId: this.params.clientId,
Object.assign(ctx.body, {
registration_access_token: ctx.oidc.bearer,
registration_client_uri: ctx.oidc.urlFor('registration_client', {
clientId: ctx.params.clientId,
}),
});
yield next;
await next();
},

@@ -140,37 +142,37 @@ ]),

function* forbiddenFields(next) {
const hit = FORBIDDEN.find(field => this.request.body[field] !== undefined);
async function forbiddenFields(ctx, next) {
const hit = FORBIDDEN.find(field => ctx.request.body[field] !== undefined);
this.assert(!hit, new errors.InvalidRequestError(
ctx.assert(!hit, new errors.InvalidRequestError(
`request MUST NOT include the "${hit}" field`));
yield next;
await next();
},
function* metaChecks(next) {
const hit = _.findKey(this.oidc.client.metadata(), findMissingKey.bind(this));
async function metaChecks(ctx, next) {
const hit = _.findKey(ctx.oidc.client.metadata(), findMissingKey.bind(ctx));
this.assert(!hit, new errors.InvalidRequestError(`${hit} must be provided`));
yield next;
ctx.assert(!hit, new errors.InvalidRequestError(`${hit} must be provided`));
await next();
},
function* equalChecks(next) {
this.assert(this.request.body.client_id === this.oidc.client.clientId,
async function equalChecks(ctx, next) {
ctx.assert(ctx.request.body.client_id === ctx.oidc.client.clientId,
new errors.InvalidRequestError(
'provided client_id does not match the authenticated client\'s one'));
if (this.request.body.client_secret) {
if (ctx.request.body.client_secret) {
const clientSecretValid = constantEquals(
new Buffer(this.request.body.client_secret, 'utf8'),
new Buffer(this.oidc.client.clientSecret, 'utf8'),
new Buffer(ctx.request.body.client_secret, 'utf8'),
new Buffer(ctx.oidc.client.clientSecret, 'utf8'),
1000);
this.assert(clientSecretValid, new errors.InvalidRequestError(
ctx.assert(clientSecretValid, new errors.InvalidRequestError(
'provided client_secret does not match the authenticated client\'s one'));
}
yield next;
await next();
},
function* clientUpdateResponse(next) {
if (this.oidc.client.noManage) {
async function clientUpdateResponse(ctx, next) {
if (ctx.oidc.client.noManage) {
throw new errors.InvalidRequestError('this client is not allowed to update its records',

@@ -180,13 +182,13 @@ 403);

provider.emit('registration_update.success', this.oidc.client, this);
provider.emit('registration_update.success', ctx.oidc.client, ctx);
const properties = {};
Object.assign(properties, this.request.body, {
client_id: this.oidc.client.clientId,
client_id_issued_at: this.oidc.client.clientIdIssuedAt,
Object.assign(properties, ctx.request.body, {
client_id: ctx.oidc.client.clientId,
client_id_issued_at: ctx.oidc.client.clientIdIssuedAt,
});
const Client = provider.Client;
const secretRequired = !this.oidc.client.clientSecret && Client.needsSecret(properties);
const secretRequired = !ctx.oidc.client.clientSecret && Client.needsSecret(properties);

@@ -200,19 +202,19 @@ if (secretRequired) {

Object.assign(properties, {
client_secret: this.oidc.client.clientSecret,
client_secret_expires_at: this.oidc.client.clientSecretExpiresAt,
client_secret: ctx.oidc.client.clientSecret,
client_secret_expires_at: ctx.oidc.client.clientSecretExpiresAt,
});
}
const client = yield instance(provider).clientAdd(properties, true);
const client = await instance(provider).clientAdd(properties, true);
this.body = client.metadata();
ctx.body = client.metadata();
Object.assign(this.body, {
registration_access_token: this.oidc.bearer,
registration_client_uri: this.oidc.urlFor('registration_client', {
clientId: this.params.clientId,
Object.assign(ctx.body, {
registration_access_token: ctx.oidc.bearer,
registration_client_uri: ctx.oidc.urlFor('registration_client', {
clientId: ctx.params.clientId,
}),
});
yield next;
await next();
},

@@ -225,14 +227,14 @@ ]),

function* clientRemoveResponse(next) {
if (this.oidc.client.noManage) {
async function clientRemoveResponse(ctx, next) {
if (ctx.oidc.client.noManage) {
throw new errors.InvalidRequestError('this client is not allowed to delete itself', 403);
}
yield instance(provider).clientRemove(this.oidc.client.clientId);
await instance(provider).clientRemove(ctx.oidc.client.clientId);
this.status = 204;
ctx.status = 204;
provider.emit('registration_delete.success', this.oidc.client, this);
provider.emit('registration_delete.success', ctx.oidc.client, ctx);
yield next;
await next();
},

@@ -239,0 +241,0 @@ ]),

@@ -32,15 +32,15 @@ 'use strict';

function* validateTokenPresence(next) {
presence.call(this, ['token']);
yield next;
async function validateTokenPresence(ctx, next) {
presence.call(ctx, ['token']);
await next();
},
function* renderTokenResponse(next) {
this.body = {};
yield next;
async function renderTokenResponse(ctx, next) {
ctx.body = {};
await next();
},
function* revokeToken() {
async function revokeToken(ctx, next) {
let tryhard;
const params = this.oidc.params;
const params = ctx.oidc.params;

@@ -88,3 +88,3 @@ switch (params.token_type_hint) {

try {
token = yield tryhard;
token = await tryhard;
} catch (err) {

@@ -102,15 +102,17 @@ if (err.message === 'invalid_token') {

this.assert(token.clientId === this.oidc.client.clientId,
ctx.assert(token.clientId === ctx.oidc.client.clientId,
new errors.InvalidRequestError('this token does not belong to you'));
yield token.destroy();
await token.destroy();
break;
default:
this.throw(400, 'unsupported_token_type', {
ctx.throw(400, 'unsupported_token_type', {
error_description: 'revocation of the presented token type is not supported',
});
}
await next();
},
]);
};

@@ -17,18 +17,16 @@ 'use strict';

function* supportedGrantTypeCheck(next) {
presence.call(this, ['grant_type']);
async function supportedGrantTypeCheck(ctx, next) {
presence.call(ctx, ['grant_type']);
const supported = instance(provider).configuration('grantTypes');
this.assert(supported.has(this.oidc.params.grant_type), 400, 'unsupported_grant_type', {
error_description: `unsupported grant_type requested (${this.oidc.params.grant_type})`,
ctx.assert(supported.has(ctx.oidc.params.grant_type), 400, 'unsupported_grant_type', {
error_description: `unsupported grant_type requested (${ctx.oidc.params.grant_type})`,
});
yield next;
await next();
},
function* allowedGrantTypeCheck(next) {
const oidc = this.oidc;
this.assert(oidc.client.grantTypeAllowed(oidc.params.grant_type), 400,
async function allowedGrantTypeCheck(ctx, next) {
ctx.assert(ctx.oidc.client.grantTypeAllowed(ctx.oidc.params.grant_type), 400,
'restricted_grant_type', {

@@ -38,7 +36,7 @@ error_description: 'requested grant type is restricted to this client',

yield next;
await next();
},
function* callTokenHandler(next) {
const grantType = this.oidc.params.grant_type;
async function callTokenHandler(ctx, next) {
const grantType = ctx.oidc.params.grant_type;

@@ -48,6 +46,6 @@ const grantTypeHandlers = instance(provider).grantTypeHandlers;

if (grantTypeHandlers.has(grantType)) {
yield grantTypeHandlers.get(grantType).call(this, next);
provider.emit('grant.success', this);
await grantTypeHandlers.get(grantType)(ctx, next);
provider.emit('grant.success', ctx);
} else {
this.throw(500, 'server_error', {
ctx.throw(500, 'server_error', {
error_description: 'not implemented grant type',

@@ -54,0 +52,0 @@ });

@@ -12,11 +12,11 @@ 'use strict';

module.exports.handler = function getAuthorizationCodeHandler(provider) {
return function* authorizationCodeResponse(next) {
presence.call(this, ['code', 'redirect_uri']);
return async function authorizationCodeResponse(ctx, next) {
presence.call(ctx, ['code', 'redirect_uri']);
const code = yield provider.AuthorizationCode.find(this.oidc.params.code, {
const code = await provider.AuthorizationCode.find(ctx.oidc.params.code, {
ignoreExpiration: true,
});
this.assert(code, new errors.InvalidGrantError('authorization code not found'));
this.assert(!code.isExpired, new errors.InvalidGrantError('authorization code is expired'));
ctx.assert(code, new errors.InvalidGrantError('authorization code not found'));
ctx.assert(!code.isExpired, new errors.InvalidGrantError('authorization code is expired'));

@@ -26,4 +26,4 @@ // PKCE check

try {
assert(this.oidc.params.code_verifier);
let expected = this.oidc.params.code_verifier;
assert(ctx.oidc.params.code_verifier);
let expected = ctx.oidc.params.code_verifier;

@@ -36,3 +36,3 @@ if (code.codeChallengeMethod === 'S256') {

} catch (err) {
this.throw(new errors.InvalidGrantError('PKCE verification failed'));
ctx.throw(new errors.InvalidGrantError('PKCE verification failed'));
}

@@ -42,20 +42,20 @@ }

try {
this.assert(!code.consumed,
ctx.assert(!code.consumed,
new errors.InvalidGrantError('authorization code already consumed'));
yield code.consume();
await code.consume();
} catch (err) {
yield code.destroy();
await code.destroy();
throw err;
}
this.assert(code.clientId === this.oidc.client.clientId,
ctx.assert(code.clientId === ctx.oidc.client.clientId,
new errors.InvalidGrantError('authorization code client mismatch'));
this.assert(code.redirectUri === this.oidc.params.redirect_uri,
ctx.assert(code.redirectUri === ctx.oidc.params.redirect_uri,
new errors.InvalidGrantError('authorization code redirect_uri mismatch'));
const account = yield provider.Account.findById(code.accountId);
const account = await provider.Account.findById(code.accountId);
this.assert(account,
ctx.assert(account,
new errors.InvalidGrantError('authorization code invalid (referenced account not found)'));

@@ -67,3 +67,3 @@

claims: code.claims,
clientId: this.oidc.client.clientId,
clientId: ctx.oidc.client.clientId,
grantId: code.grantId,

@@ -74,3 +74,3 @@ scope: code.scope,

const accessToken = yield at.save();
const accessToken = await at.save();
const tokenType = 'Bearer';

@@ -80,3 +80,3 @@ const expiresIn = AccessToken.expiresIn;

let refreshToken;
const grantPresent = this.oidc.client.grantTypes.indexOf('refresh_token') !== -1;
const grantPresent = ctx.oidc.client.grantTypes.indexOf('refresh_token') !== -1;
const shouldIssue = instance(provider).configuration('features.refreshToken') ||

@@ -93,3 +93,3 @@ code.scope.split(' ').indexOf('offline_access') !== -1;

claims: code.claims,
clientId: this.oidc.client.clientId,
clientId: ctx.oidc.client.clientId,
grantId: code.grantId,

@@ -101,11 +101,11 @@ nonce: code.nonce,

refreshToken = yield rt.save();
refreshToken = await rt.save();
}
const IdToken = provider.IdToken;
const token = new IdToken(Object.assign({}, yield Promise.resolve(account.claims()), {
const token = new IdToken(Object.assign({}, await Promise.resolve(account.claims()), {
acr: code.acr,
amr: code.amr,
auth_time: code.authTime,
}), this.oidc.client.sectorIdentifier);
}), ctx.oidc.client.sectorIdentifier);

@@ -120,5 +120,5 @@ token.scope = code.scope;

const idToken = yield token.sign(this.oidc.client);
const idToken = await token.sign(ctx.oidc.client);
this.body = {
ctx.body = {
access_token: accessToken,

@@ -131,3 +131,3 @@ expires_in: expiresIn,

yield next;
await next();
};

@@ -134,0 +134,0 @@ };

'use strict';
module.exports.handler = function getClientCredentialsHandler(provider) {
return function* clientCredentialsResponse(next) {
return async function clientCredentialsResponse(ctx, next) {
const ClientCredentials = provider.ClientCredentials;
const at = new ClientCredentials({
clientId: this.oidc.client.clientId,
scope: this.oidc.params.scope,
clientId: ctx.oidc.client.clientId,
scope: ctx.oidc.params.scope,
});
const token = yield at.save();
const token = await at.save();
const tokenType = 'Bearer';
const expiresIn = ClientCredentials.expiresIn;
this.body = { access_token: token, expires_in: expiresIn, token_type: tokenType };
ctx.body = { access_token: token, expires_in: expiresIn, token_type: tokenType };
yield next;
await next();
};

@@ -19,0 +19,0 @@ };

@@ -9,4 +9,4 @@ 'use strict';

module.exports.handler = function getRefreshTokenHandler(provider) {
return function* refreshTokenResponse(next) {
presence.call(this, ['refresh_token']);
return async function refreshTokenResponse(ctx, next) {
presence.call(ctx, ['refresh_token']);

@@ -18,10 +18,10 @@ const RefreshToken = provider.RefreshToken;

const refreshToken = yield RefreshToken.find(
this.oidc.params.refresh_token, {
const refreshToken = await RefreshToken.find(
ctx.oidc.params.refresh_token, {
ignoreExpiration: true,
});
this.assert(refreshToken, new errors.InvalidGrantError('refresh token not found'));
this.assert(!refreshToken.isExpired, new errors.InvalidGrantError('refresh token is expired'));
this.assert(refreshToken.clientId === this.oidc.client.clientId,
ctx.assert(refreshToken, new errors.InvalidGrantError('refresh token not found'));
ctx.assert(!refreshToken.isExpired, new errors.InvalidGrantError('refresh token is expired'));
ctx.assert(refreshToken.clientId === ctx.oidc.client.clientId,
new errors.InvalidGrantError('refresh token client mismatch'));

@@ -31,6 +31,6 @@

if (this.oidc.params.scope) {
const missing = _.difference(this.oidc.params.scope.split(' '), refreshTokenScopes);
if (ctx.oidc.params.scope) {
const missing = _.difference(ctx.oidc.params.scope.split(' '), refreshTokenScopes);
this.assert(_.isEmpty(missing), 400, 'invalid_scope', {
ctx.assert(_.isEmpty(missing), 400, 'invalid_scope', {
error_description: 'refresh token missing requested scope',

@@ -41,5 +41,5 @@ scope: missing.join(' '),

const account = yield Account.findById(refreshToken.accountId);
const account = await Account.findById(refreshToken.accountId);
this.assert(account,
ctx.assert(account,
new errors.InvalidGrantError('refresh token invalid (referenced account not found)'));

@@ -50,17 +50,17 @@

claims: refreshToken.claims,
clientId: this.oidc.client.clientId,
clientId: ctx.oidc.client.clientId,
grantId: refreshToken.grantId,
scope: this.oidc.params.scope || refreshToken.scope,
scope: ctx.oidc.params.scope || refreshToken.scope,
sid: refreshToken.sid,
});
const accessToken = yield at.save();
const accessToken = await at.save();
const tokenType = 'Bearer';
const expiresIn = AccessToken.expiresIn;
const token = new IdToken(Object.assign({}, yield Promise.resolve(account.claims()), {
const token = new IdToken(Object.assign({}, await Promise.resolve(account.claims()), {
acr: refreshToken.acr,
amr: refreshToken.amr,
auth_time: refreshToken.authTime,
}), this.oidc.client.sectorIdentifier);
}), ctx.oidc.client.sectorIdentifier);

@@ -72,16 +72,16 @@ token.scope = refreshToken.scope;

token.set('at_hash', accessToken);
token.set('rt_hash', this.oidc.params.refresh_token);
token.set('rt_hash', ctx.oidc.params.refresh_token);
token.set('sid', refreshToken.sid);
const idToken = yield token.sign(this.oidc.client);
const idToken = await token.sign(ctx.oidc.client);
this.body = {
ctx.body = {
access_token: accessToken,
expires_in: expiresIn,
id_token: idToken,
refresh_token: this.oidc.params.refresh_token,
refresh_token: ctx.oidc.params.refresh_token,
token_type: tokenType,
};
yield next;
await next();
};

@@ -88,0 +88,0 @@ };

@@ -27,9 +27,9 @@ 'use strict';

return compose([
function* setAuthenticate(next) {
yield next;
if (this.status === 401) {
async function setAuthenticate(ctx, next) {
await next();
if (ctx.status === 401) {
const wwwAuth = _.chain({
realm: provider.issuer,
})
.merge(this.body)
.merge(ctx.body)
.map((val, key) => `${key}="${val}"`)

@@ -39,3 +39,3 @@ .value()

this.set('WWW-Authenticate', `Bearer ${wwwAuth}`);
ctx.set('WWW-Authenticate', `Bearer ${wwwAuth}`);
}

@@ -52,17 +52,17 @@ },

function* validateBearer(next) {
const accessToken = yield provider.AccessToken.find(this.oidc.bearer);
this.assert(accessToken, new errors.InvalidTokenError());
async function validateBearer(ctx, next) {
const accessToken = await provider.AccessToken.find(ctx.oidc.bearer);
ctx.assert(accessToken, new errors.InvalidTokenError());
this.oidc.accessToken = accessToken;
yield next;
ctx.oidc.accessToken = accessToken;
await next();
},
function* validateScope(next) {
if (this.oidc.params.scope) {
const accessTokenScopes = this.oidc.accessToken.scope.split(' ');
const missing = _.difference(this.oidc.params.scope.split(' '),
async function validateScope(ctx, next) {
if (ctx.oidc.params.scope) {
const accessTokenScopes = ctx.oidc.accessToken.scope.split(' ');
const missing = _.difference(ctx.oidc.params.scope.split(' '),
accessTokenScopes);
this.assert(_.isEmpty(missing), 400, 'invalid_scope', {
ctx.assert(_.isEmpty(missing), 400, 'invalid_scope', {
error_description: 'access token missing requested scope',

@@ -72,32 +72,32 @@ scope: missing.join(' '),

}
yield next;
await next();
},
function* loadClient(next) {
const client = yield provider.Client.find(this.oidc.accessToken.clientId);
this.assert(client, new errors.InvalidTokenError());
async function loadClient(ctx, next) {
const client = await provider.Client.find(ctx.oidc.accessToken.clientId);
ctx.assert(client, new errors.InvalidTokenError());
this.oidc.client = client;
ctx.oidc.client = client;
yield next;
await next();
},
function* loadAccount(next) {
const account = yield provider.Account.findById(this.oidc.accessToken.accountId);
async function loadAccount(ctx, next) {
const account = await provider.Account.findById(ctx.oidc.accessToken.accountId);
this.assert(account, new errors.InvalidTokenError());
ctx.assert(account, new errors.InvalidTokenError());
this.oidc.account = account;
ctx.oidc.account = account;
yield next;
await next();
},
function* respond() {
const claims = _.get(this.oidc.accessToken, 'claims.userinfo', {});
const scope = this.oidc.params.scope || this.oidc.accessToken.scope;
const client = this.oidc.client;
async function respond(ctx, next) {
const claims = _.get(ctx.oidc.accessToken, 'claims.userinfo', {});
const scope = ctx.oidc.params.scope || ctx.oidc.accessToken.scope;
const client = ctx.oidc.client;
if (client.userinfoSignedResponseAlg || client.userinfoEncryptedResponseAlg) {
const IdToken = provider.IdToken;
const token = new IdToken(yield Promise.resolve(this.oidc.account.claims()),
const token = new IdToken(await Promise.resolve(ctx.oidc.account.claims()),
client.sectorIdentifier);

@@ -108,9 +108,9 @@

this.body = yield token.sign(client, {
expiresAt: this.oidc.accessToken.exp,
ctx.body = await token.sign(client, {
expiresAt: ctx.oidc.accessToken.exp,
use: 'userinfo',
});
this.type = 'application/jwt; charset=utf-8';
ctx.type = 'application/jwt; charset=utf-8';
} else {
const mask = new Claims(yield Promise.resolve(this.oidc.account.claims()),
const mask = new Claims(await Promise.resolve(ctx.oidc.account.claims()),
client.sectorIdentifier);

@@ -121,6 +121,8 @@

this.body = mask.result();
ctx.body = mask.result();
}
await next();
},
]);
};
'use strict';
module.exports = function webfingerAction(provider) {
return function* renderWebfingerResponse(next) {
this.body = {
return async function renderWebfingerResponse(ctx, next) {
ctx.body = {
links: [{

@@ -10,7 +10,7 @@ href: provider.issuer,

}],
subject: this.query.resource,
subject: ctx.query.resource,
};
this.type = 'application/jrd+json';
yield next;
ctx.type = 'application/jrd+json';
await next();
};
};
'use strict';
const koa = require('koa');
const Koa = require('koa');
const Router = require('koa-router');

@@ -34,3 +34,3 @@ const getCors = require('kcors');

const configuration = instance(this).configuration();
const app = koa();
const app = new Koa();

@@ -133,2 +133,3 @@ instance(this).app = app;

const interaction = getInteraction(this);
get('/interaction/:grant', error(this), interaction.get);

@@ -135,0 +136,0 @@ post('interaction', '/interaction/:grant/submit', error(this), interaction.post);

@@ -8,5 +8,5 @@ 'use strict';

module.exports = provider => function* authorizationErrorHandler(next) { // eslint-disable-line consistent-return, max-len
module.exports = provider => async function authorizationErrorHandler(ctx, next) { // eslint-disable-line consistent-return, max-len
try {
yield next;
await next();
} catch (caught) {

@@ -17,8 +17,8 @@ let err = caught;

let params;
params = this.oidc.params;
params = params || (this.method === 'POST' ? this.request.body : this.query) ||
params = ctx.oidc.params;
params = params || (ctx.method === 'POST' ? ctx.request.body : ctx.query) ||
/* istanbul ignore next */ {};
if (this.oidc.client && params.redirect_uri && !this.oidc.redirectUriCheckPerformed) {
if (!this.oidc.client.redirectUriAllowed(params.redirect_uri)) {
if (ctx.oidc.client && params.redirect_uri && !ctx.oidc.redirectUriCheckPerformed) {
if (!ctx.oidc.client.redirectUriAllowed(params.redirect_uri)) {
err = new errors.RedirectUriMismatchError();

@@ -28,3 +28,3 @@ }

this.status = err.statusCode || 500;
ctx.status = err.statusCode || 500;

@@ -41,3 +41,3 @@ if (err.expose) {

provider.emit(out.error === 'server_error' ?
'server_error' : 'authorization.error', err, this);
'server_error' : 'authorization.error', err, ctx);

@@ -48,3 +48,3 @@ // redirect uri error should render instead of redirect to uri

const renderError = instance(provider).configuration('renderError');
return renderError.call(this, out);
return renderError.call(ctx, out);
}

@@ -55,10 +55,10 @@

instance(provider).responseModes.get(params.response_mode)
.call(this, params.redirect_uri, out);
.call(ctx, params.redirect_uri, out);
} else if (params.response_mode === 'form_post') {
formPost.call(this, params.redirect_uri, out);
formPost.call(ctx, params.redirect_uri, out);
} else {
const uri = redirectUri(params.redirect_uri, out, params.response_mode);
this.redirect(uri);
ctx.redirect(uri);
}
}
};

@@ -6,10 +6,10 @@ 'use strict';

module.exports = function* checkDupes(next) {
const dupes = _.chain(this.oidc.params).pickBy(Array.isArray).keys().value();
module.exports = async function checkDupes(ctx, next) {
const dupes = _.chain(ctx.oidc.params).pickBy(Array.isArray).keys().value();
// Validate: no dup params
this.assert(_.isEmpty(dupes),
ctx.assert(_.isEmpty(dupes),
new errors.InvalidRequestError(`parameters must not be provided twice. ${dupes.join(',')}`));
yield next;
await next();
};

@@ -8,9 +8,9 @@ 'use strict';

return function* parseBodyIfPost(next) {
if (this.method === 'POST') {
yield parseBody.call(this, next);
return async function parseBodyIfPost(ctx, next) {
if (ctx.method === 'POST') {
await parseBody(ctx, next);
} else {
yield next;
await next();
}
};
};

@@ -7,6 +7,6 @@ 'use strict';

const OIDCContext = getContext(provider);
return function* contextEnsureOidc(next) {
Object.defineProperty(this, 'oidc', { value: new OIDCContext(this) });
yield next;
return async function contextEnsureOidc(ctx, next) {
Object.defineProperty(ctx, 'oidc', { value: new OIDCContext(ctx) });
await next();
};
};

@@ -6,8 +6,8 @@ 'use strict';

module.exports = function getErrorHandler(provider, eventName) {
return function* apiErrorHandler(next) {
return async function apiErrorHandler(ctx, next) {
try {
yield next;
await next();
} catch (err) {
const out = {};
this.status = err.statusCode || 500;
ctx.status = err.statusCode || 500;

@@ -24,13 +24,13 @@ if (err.expose) {

// browser requests end up rendering the html error instead
if (this.accepts('json', 'html') === 'html') {
if (ctx.accepts('json', 'html') === 'html') {
const renderError = instance(provider).configuration('renderError');
renderError.call(this, out);
renderError.call(ctx, out);
} else {
this.body = out;
ctx.body = out;
}
if (out.error === 'server_error') {
provider.emit('server_error', err, this);
provider.emit('server_error', err, ctx);
} else if (eventName) {
provider.emit(eventName, err, this);
provider.emit(eventName, err, ctx);
}

@@ -37,0 +37,0 @@ }

@@ -6,12 +6,12 @@ 'use strict';

module.exports = function* findClientId(next) {
this.oidc.authorization = {};
module.exports = async function findClientId(ctx, next) {
ctx.oidc.authorization = {};
if (this.headers.authorization) {
if (ctx.headers.authorization) {
// client_secret_basic
this.assert(!this.oidc.params.client_id, new errors.InvalidRequestError(
ctx.assert(!ctx.oidc.params.client_id, new errors.InvalidRequestError(
'combining multiple client authentication mechanism is no good'));
const parts = this.headers.authorization.split(' ');
this.assert(parts.length === 2 && parts[0] === 'Basic',
const parts = ctx.headers.authorization.split(' ');
ctx.assert(parts.length === 2 && parts[0] === 'Basic',
new errors.InvalidRequestError('invalid authorization header value format'));

@@ -22,30 +22,30 @@

this.assert(i !== -1,
ctx.assert(i !== -1,
new errors.InvalidRequestError('invalid authorization header value format'));
this.oidc.authorization.clientId = basic.slice(0, i);
this.oidc.authorization.clientSecret = basic.slice(i + 1);
} else if (this.oidc.params.client_id && !this.oidc.params.client_assertion) {
ctx.oidc.authorization.clientId = basic.slice(0, i);
ctx.oidc.authorization.clientSecret = basic.slice(i + 1);
} else if (ctx.oidc.params.client_id && !ctx.oidc.params.client_assertion) {
// client_secret_post
this.oidc.authorization.clientId = this.oidc.params.client_id;
} else if (this.oidc.params.client_assertion) {
ctx.oidc.authorization.clientId = ctx.oidc.params.client_id;
} else if (ctx.oidc.params.client_assertion) {
// client_secret_jwt and private_key_jwt
const assertionSub = (() => {
try {
return JSON.parse(base64url(this.oidc.params.client_assertion.split('.')[1])).sub;
return JSON.parse(base64url(ctx.oidc.params.client_assertion.split('.')[1])).sub;
} catch (err) {
return this.throw(new errors.InvalidRequestError('invalid client_assertion'));
return ctx.throw(new errors.InvalidRequestError('invalid client_assertion'));
}
})();
this.assert(!this.oidc.params.client_id || assertionSub === this.oidc.params.client_id,
ctx.assert(!ctx.oidc.params.client_id || assertionSub === ctx.oidc.params.client_id,
new errors.InvalidRequestError('subject of client_assertion must be the same as client_id'));
this.oidc.authorization.clientId = assertionSub;
ctx.oidc.authorization.clientId = assertionSub;
}
this.assert(this.oidc.authorization.clientId,
ctx.assert(ctx.oidc.authorization.clientId,
new errors.InvalidClientError('no client authentication mechanism provided'));
yield next;
await next();
};

@@ -15,7 +15,7 @@ 'use strict';

return function* assembleParams(next) {
const params = this.method === 'POST' ? this.request.body : this.query;
this.oidc.params = new Params(params);
yield next;
return async function assembleParams(ctx, next) {
const params = ctx.method === 'POST' ? ctx.request.body : ctx.query;
ctx.oidc.params = new Params(params);
await next();
};
};

@@ -5,7 +5,7 @@ 'use strict';

module.exports = function* invalidRoute(next) {
yield next;
if (this.status === 404 && this.message === 'Not Found') {
this.throw(new errors.InvalidRequestError('unrecognized route', 404));
module.exports = async function invalidRoute(ctx, next) {
await next();
if (ctx.status === 404 && ctx.message === 'Not Found') {
ctx.throw(new errors.InvalidRequestError('unrecognized route', 404));
}
};

@@ -6,12 +6,12 @@ 'use strict';

module.exports = function getLoadClient(provider) {
return function* loadClient(next) {
const client = yield provider.Client.find(this.oidc.authorization.clientId);
return async function loadClient(ctx, next) {
const client = await provider.Client.find(ctx.oidc.authorization.clientId);
this.assert(client, new errors.InvalidClientError(
ctx.assert(client, new errors.InvalidClientError(
'invalid client authentication provided (client not found)'));
this.oidc.client = client;
ctx.oidc.client = client;
yield next;
await next();
};
};
'use strict';
module.exports = function* noCache(next) {
this.set('Pragma', 'no-cache');
this.set('Cache-Control', 'no-cache, no-store');
yield next;
module.exports = async function noCache(ctx, next) {
ctx.set('Pragma', 'no-cache');
ctx.set('Cache-Control', 'no-cache, no-store');
await next();
};

@@ -11,4 +11,4 @@ 'use strict';

module.exports = function getResumeAction(provider) {
return function* resumeAction(next) {
this.oidc.uuid = this.params.grant;
return async function resumeAction(ctx, next) {
ctx.oidc.uuid = ctx.params.grant;

@@ -18,3 +18,3 @@ const cookieOptions = instance(provider).configuration('cookies.short');

try {
this.query = j(this.cookies.get('_grant', cookieOptions));
ctx.query = j(ctx.cookies.get('_grant', cookieOptions));
} catch (err) {

@@ -26,3 +26,3 @@ throw new errors.InvalidRequestError('authorization request has expired');

try {
return j(this.cookies.get('_grant_result', cookieOptions));
return j(ctx.cookies.get('_grant_result', cookieOptions));
} catch (err) {

@@ -32,27 +32,27 @@ return {};

})();
this.cookies.set('_grant_result', null, cookieOptions);
ctx.cookies.set('_grant_result', null, cookieOptions);
if (result.login) {
if (!result.login.remember) this.oidc.session.transient = true;
if (!result.login.remember) ctx.oidc.session.transient = true;
if (this.oidc.session.account !== result.login.account) {
delete this.oidc.session.authorizations;
if (ctx.oidc.session.account !== result.login.account) {
delete ctx.oidc.session.authorizations;
}
this.oidc.session.account = result.login.account;
this.oidc.session.loginTs = result.login.ts;
ctx.oidc.session.account = result.login.account;
ctx.oidc.session.loginTs = result.login.ts;
}
if (result.consent && result.consent.scope !== undefined) {
this.query.scope = String(result.consent.scope);
ctx.query.scope = String(result.consent.scope);
}
if (!_.isEmpty(result) && !this.oidc.session.sidFor(this.query.client_id)) {
this.oidc.session.sidFor(this.query.client_id, uuid());
if (!_.isEmpty(result) && !ctx.oidc.session.sidFor(ctx.query.client_id)) {
ctx.oidc.session.sidFor(ctx.query.client_id, uuid());
}
this.oidc.result = result;
ctx.oidc.result = result;
yield next;
await next();
};
};

@@ -11,10 +11,10 @@ 'use strict';

return function* selectiveBody(next) {
if (this.is(only)) {
yield bodyParser.call(this, next);
return async function selectiveBody(ctx, next) {
if (ctx.is(only)) {
await bodyParser(ctx, next);
} else {
const msg = `only ${only} content-type ${this.method} bodies are supported`;
this.throw(new errors.InvalidRequestError(msg));
const msg = `only ${only} content-type ${ctx.method} bodies are supported`;
ctx.throw(new errors.InvalidRequestError(msg));
}
};
};
'use strict';
module.exports = function getSessionHandler(provider) {
return function* sessionHandler(next) {
this.oidc.session = yield provider.Session.get(this);
yield next;
return async function sessionHandler(ctx, next) {
ctx.oidc.session = await provider.Session.get(ctx);
await next();
if (this.oidc.session.transient) {
this.response.get('set-cookie').forEach((cookie, index, ary) => {
if (ctx.oidc.session.transient) {
ctx.response.get('set-cookie').forEach((cookie, index, ary) => {
if (cookie.startsWith('_session') && !cookie.includes('expires=Thu, 01 Jan 1970')) {

@@ -16,4 +16,4 @@ ary[index] = cookie.replace(/(; ?expires=([\w\d:, ]+))/, ''); // eslint-disable-line no-param-reassign

yield this.oidc.session.save();
await ctx.oidc.session.save();
};
};

@@ -11,7 +11,7 @@ 'use strict';

return function* tokenAuth(next) {
switch (this.oidc.client.tokenEndpointAuthMethod) {
return async function tokenAuth(ctx, next) {
switch (ctx.oidc.client.tokenEndpointAuthMethod) {
case 'none':
this.throw(new errors.InvalidRequestError('client not supposed to access token endpoint'));
ctx.throw(new errors.InvalidRequestError('client not supposed to access token endpoint'));

@@ -21,11 +21,11 @@ /* istanbul ignore next */

case 'client_secret_post': {
const params = this.oidc.params;
const params = ctx.oidc.params;
this.assert(params.client_id, new errors.InvalidRequestError(
ctx.assert(params.client_id, new errors.InvalidRequestError(
'client_id must be provided in the body'));
this.assert(params.client_secret, new errors.InvalidRequestError(
ctx.assert(params.client_secret, new errors.InvalidRequestError(
'client_secret must be provided in the body'));
tokenCredentialAuth.call(this, this.oidc.client.clientSecret, params.client_secret);
tokenCredentialAuth.call(ctx, ctx.oidc.client.clientSecret, params.client_secret);

@@ -36,5 +36,5 @@ break;

yield tokenJwtAuth.call(this, this.oidc.client.keystore,
this.oidc.client.tokenEndpointAuthSigningAlg ?
[this.oidc.client.tokenEndpointAuthSigningAlg] : ['HS256', 'HS384', 'HS512']);
await tokenJwtAuth.call(ctx, ctx.oidc.client.keystore,
ctx.oidc.client.tokenEndpointAuthSigningAlg ?
[ctx.oidc.client.tokenEndpointAuthSigningAlg] : ['HS256', 'HS384', 'HS512']);

@@ -44,5 +44,5 @@ break;

yield tokenJwtAuth.call(this, this.oidc.client.keystore,
this.oidc.client.tokenEndpointAuthSigningAlg ?
[this.oidc.client.tokenEndpointAuthSigningAlg] : ['ES256', 'ES384', 'ES512', 'RS256',
await tokenJwtAuth.call(ctx, ctx.oidc.client.keystore,
ctx.oidc.client.tokenEndpointAuthSigningAlg ?
[ctx.oidc.client.tokenEndpointAuthSigningAlg] : ['ES256', 'ES384', 'ES512', 'RS256',
'RS384', 'RS512', 'PS256', 'PS384', 'PS512']);

@@ -52,16 +52,16 @@

default: { // Client_secret_basic
const auth = this.oidc.authorization;
const auth = ctx.oidc.authorization;
this.assert(auth.clientId, new errors.InvalidRequestError(
ctx.assert(auth.clientId, new errors.InvalidRequestError(
'client_id must be provided in the Authorization header'));
this.assert(auth.clientSecret, new errors.InvalidRequestError(
ctx.assert(auth.clientSecret, new errors.InvalidRequestError(
'client_secret must be provided in the Authorization header'));
tokenCredentialAuth.call(this, this.oidc.client.clientSecret, auth.clientSecret);
tokenCredentialAuth.call(ctx, ctx.oidc.client.clientSecret, auth.clientSecret);
}
}
yield next;
await next();
};
};

@@ -10,3 +10,3 @@ 'use strict';

return function* tokenJwtAuth(keystore, algorithms) {
return async function tokenJwtAuth(keystore, algorithms) {
const tokenUri = this.oidc.urlFor('token');

@@ -68,7 +68,7 @@

const unique = yield uniqueCheck.call(this, payload.jti, payload.exp);
const unique = await uniqueCheck.call(this, payload.jti, payload.exp);
this.assert(unique, new errors.InvalidRequestError('jwt-bearer tokens must only be used once'));
try {
yield JWT.verify(this.oidc.params.client_assertion, keystore, {
await JWT.verify(this.oidc.params.client_assertion, keystore, {
audience: tokenUri,

@@ -75,0 +75,0 @@ issuer: this.oidc.client.clientId,

@@ -7,10 +7,10 @@ {

"buffer-equals-constant": "^1.0.0",
"ejs": "^2.5.2",
"got": "^6.1.1",
"http-errors": "^1.4.0",
"kcors": "^1.2.1",
"koa": "^1.0.0",
"koa-body": "^1.2.1",
"koa-compose": "^2.3.0",
"koa-router": "^5.2.3",
"kcors": "next",
"koa": "next",
"koa-body": "next",
"koa-compose": "next",
"ejs": "^2.5.2",
"koa-router": "next",
"lodash": "^4.5.0",

@@ -26,3 +26,2 @@ "lru-cache": "^4.0.0",

"chai": "^3.5.0",
"co-mocha": "^1.1.2",
"cookiejar": "*",

@@ -34,6 +33,5 @@ "eslint": "^3.0.0",

"koa-ejs": "^3.0.0",
"koa-mount": "^1.3.0",
"koa-rewrite": "^1.1.1",
"koa-mount": "next",
"koa-rewrite": "next",
"mocha": "^3.0.0",
"mocha-generators": "^1.2.0",
"moment": "^2.14.1",

@@ -48,3 +46,3 @@ "nock": "^9.0.2",

"engines": {
"node": ">=4"
"node": ">=7"
},

@@ -70,6 +68,9 @@ "license": "MIT",

},
"version": "1.2.0",
"version": "2.0.0-alpha.1.2.0",
"files": [
"lib"
]
],
"publishConfig": {
"tag": "next"
}
}

@@ -17,2 +17,3 @@ # oidc-provider

<!-- TOC START min:2 max:2 link:true update:true -->
- ['next' branch/release](#next-branchrelease)
- [Implemented specs & features](#implemented-specs--features)

@@ -26,2 +27,15 @@ - [Get started](#get-started)

## 'next' branch/release
This branch is being kept up to date with the latest master only having the internal dependencies
being koa2 based, therefore requiring ES7 async/await capable node runtime (or live transpile).
There are no extra features or master-unreleased features. 2.0.0 of this library will come when koa2
releases as latest and when ES7 async/await lands in LTS nodejs release (probably LTSv8).
You can use this library if you already use node stable with `--harmony_async_await`, just declare
your dependency in package.json with the @next distribution tag.
The published versions also use pre-release version scheme 2.0.0-alpha.x.y.z with xyz being the same
as the corresponding latest release. i.e. 2.0.0-alpha.1.2.0 is essentially version 1.2.0 only with
the updated dependencies.
## Implemented specs & features

@@ -61,6 +75,6 @@

```bash
$ git clone https://github.com/panva/node-oidc-provider.git oidc-provider
$ git clone -b next https://github.com/panva/node-oidc-provider.git oidc-provider
$ cd oidc-provider
$ npm install
$ node example
$ node --harmony_async_await example
```

@@ -77,3 +91,3 @@ Visiting `http://localhost:3000/.well-known/openid-configuration` will help you to discover how the

```
$ npm install oidc-provider --save
$ npm install oidc-provider@next --save
```

@@ -80,0 +94,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc