oidc-provider
Version:
OAuth 2.0 Authorization Server implementation for Node.js with OpenID Connect
112 lines (90 loc) • 3.11 kB
JavaScript
import upperFirst from '../../helpers/_/upper_first.js';
import camelCase from '../../helpers/_/camel_case.js';
import nanoid from '../../helpers/nanoid.js';
import * as errors from '../../helpers/errors.js';
import instance from '../../helpers/weak_cache.js';
import Params from '../../helpers/params.js';
import formPost from '../../response_modes/form_post.js';
import epochTime from '../../helpers/epoch_time.js';
export default async function resumeAction(allowList, resumeRouteName, ctx, next) {
const cookieOptions = instance(ctx.oidc.provider).configuration.cookies.short;
const cookieId = ctx.cookies.get(
ctx.oidc.provider.cookieName('resume'),
cookieOptions,
);
if (!cookieId) {
throw new errors.SessionNotFound('authorization request has expired');
}
const interactionSession = await ctx.oidc.provider.Interaction.find(cookieId);
if (!interactionSession) {
throw new errors.SessionNotFound('interaction session not found');
}
ctx.oidc.entity('Interaction', interactionSession);
if (cookieId !== interactionSession.uid) {
throw new errors.SessionNotFound('authorization session and cookie identifier mismatch');
}
const {
result,
params: storedParams = {},
trusted = [],
session: originSession,
} = interactionSession;
const { session } = ctx.oidc;
if (originSession?.uid && originSession.uid !== session.uid) {
throw new errors.SessionNotFound('interaction session and authentication session mismatch');
}
if (
result?.login
&& session.accountId
&& session.accountId !== result.login.accountId
) {
if (interactionSession.session?.uid) {
delete interactionSession.session.uid;
await interactionSession.save(interactionSession.exp - epochTime());
}
session.state = {
secret: nanoid(),
clientId: storedParams.client_id,
postLogoutRedirectUri: ctx.oidc.urlFor(ctx.oidc.route, ctx.params),
};
formPost(ctx, ctx.oidc.urlFor('end_session_confirm'), {
xsrf: session.state.secret,
logout: 'yes',
});
return;
}
await interactionSession.destroy();
const params = new (Params(allowList))(storedParams);
ctx.oidc.params = params;
ctx.oidc.trusted = trusted;
ctx.oidc.redirectUriCheckPerformed = true;
const clearOpts = {
...cookieOptions,
path: new URL(ctx.oidc.urlFor(resumeRouteName, { uid: interactionSession.uid })).pathname,
};
ctx.cookies.set(
ctx.oidc.provider.cookieName('resume'),
null,
clearOpts,
);
if (result?.error) {
const className = upperFirst(camelCase(result.error));
if (errors[className]) {
throw new errors[className](result.error_description);
}
throw new errors.CustomOIDCProviderError(result.error, result.error_description);
}
if (result?.login) {
const {
remember = true, accountId, ts: loginTs, amr, acr,
} = result.login;
session.loginAccount({
accountId, loginTs, amr, acr, transient: !remember,
});
}
ctx.oidc.result = result;
if (!session.new) {
session.resetIdentifier();
}
await next();
}