Skip to content

Commit

Permalink
improve: Also pass along a state (nonce) paramater.
Browse files Browse the repository at this point in the history
bug: getodk#1134

It's not needed for CSRF protection because code_challenge does this, but the Authentik IDP will return &state= in the query string.  This will trigger node-openid-client to fail a check.
  • Loading branch information
openbrian committed May 1, 2024
1 parent d036f2e commit 06763fe
Showing 1 changed file with 8 additions and 2 deletions.
10 changes: 8 additions & 2 deletions lib/resources/oidc.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ const ONE_HOUR = 60 * 60 * 1000;
// * https://bugs.chromium.org/p/chromium/issues/detail?id=1056543
const CODE_VERIFIER_COOKIE = (HTTPS_ENABLED ? '__Secure-' : '') + 'ocv';
const NEXT_COOKIE = (HTTPS_ENABLED ? '__Secure-' : '') + 'next'; // eslint-disable-line no-multi-spaces
const STATE_COOKIE = (HTTPS_ENABLED ? '__Secure-' : '') + 'oidcstate';
const callbackCookieProps = {
httpOnly: true,
secure: HTTPS_ENABLED,
Expand Down Expand Up @@ -102,15 +103,18 @@ module.exports = (service, endpoint) => {
const client = await getClient();
const code_verifier = generators.codeVerifier(); // eslint-disable-line camelcase

// State is not strictly required because PKCS (code_challenge) protects us from CSRF attacks.
const state = generators.state(16);
const code_challenge = generators.codeChallenge(code_verifier); // eslint-disable-line camelcase

const authUrl = client.authorizationUrl({
scope: SCOPES.join(' '),
resource: `${envDomain}/v1`,
state,
code_challenge,
code_challenge_method: CODE_CHALLENGE_METHOD,
});

res.cookie(STATE_COOKIE, state, { ...callbackCookieProps, maxAge: ONE_HOUR });
res.cookie(CODE_VERIFIER_COOKIE, code_verifier, { ...callbackCookieProps, maxAge: ONE_HOUR });

const { next } = req.query;
Expand All @@ -129,15 +133,17 @@ module.exports = (service, endpoint) => {

service.get('/oidc/callback', endpoint.html(async (container, _, req, res) => {
try {
const state = req.cookies[STATE_COOKIE];
const code_verifier = req.cookies[CODE_VERIFIER_COOKIE]; // eslint-disable-line camelcase
const next = req.cookies[NEXT_COOKIE]; // eslint-disable-line no-multi-spaces
res.clearCookie(STATE_COOKIE, callbackCookieProps);
res.clearCookie(CODE_VERIFIER_COOKIE, callbackCookieProps);
res.clearCookie(NEXT_COOKIE, callbackCookieProps); // eslint-disable-line no-multi-spaces

const client = await getClient();

const params = client.callbackParams(req);
const tokenSet = await client.callback(getRedirectUri(), params, { code_verifier });
const tokenSet = await client.callback(getRedirectUri(), params, { state, code_verifier });

const { access_token } = tokenSet;

Expand Down

0 comments on commit 06763fe

Please sign in to comment.