Skip to content

Commit

Permalink
fix(DPoP,PAR,JAR): validate DPoP before invalidating JAR during PAR
Browse files Browse the repository at this point in the history
  • Loading branch information
panva committed Jan 8, 2024
1 parent 3f86cc0 commit ca0f999
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 9 deletions.
18 changes: 10 additions & 8 deletions lib/actions/authorization/check_dpop_jkt.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,20 @@ import epochTime from '../../helpers/epoch_time.js';
* @throws: invalid_request
*/
export default async function checkDpopJkt(ctx, next) {
const { params } = ctx.oidc;
const { params, route } = ctx.oidc;

const dPoP = await dpopValidate(ctx);
if (dPoP) {
const { ReplayDetection } = ctx.oidc.provider;
const unique = await ReplayDetection.unique(
ctx.oidc.client.clientId,
dPoP.jti,
epochTime() + 300,
);
if (route !== 'pushed_authorization_request') {
const { ReplayDetection } = ctx.oidc.provider;
const unique = await ReplayDetection.unique(
ctx.oidc.client.clientId,
dPoP.jti,
epochTime() + 300,
);

ctx.assert(unique, new InvalidRequest('DPoP proof JWT Replay detected'));
ctx.assert(unique, new InvalidRequest('DPoP proof JWT Replay detected'));
}

if (params.dpop_jkt && params.dpop_jkt !== dPoP.thumbprint) {
throw new InvalidRequest('DPoP proof key thumbprint does not match dpop_jkt');
Expand Down
15 changes: 15 additions & 0 deletions lib/actions/authorization/process_request_object.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import * as JWT from '../../helpers/jwt.js';
import instance from '../../helpers/weak_cache.js';
import { InvalidRequest, InvalidRequestObject, OIDCProviderError } from '../../helpers/errors.js';
import isPlainObject from '../../helpers/_/is_plain_object.js';
import dpopValidate from '../../helpers/validate_dpop.js';
import epochTime from '../../helpers/epoch_time.js';

import checkResponseMode from './check_response_mode.js';

Expand Down Expand Up @@ -228,6 +230,19 @@ export default async function processRequestObject(PARAM_LIST, rejectDupesMiddle
}

if (!pushedRequestObject && payload.jti && payload.exp && payload.iss) {
if (route === 'pushed_authorization_request') {
const dPoP = await dpopValidate(ctx);
if (dPoP) {
const { ReplayDetection } = ctx.oidc.provider;
const unique = await ReplayDetection.unique(
ctx.oidc.client.clientId,
dPoP.jti,
epochTime() + 300,
);

ctx.assert(unique, new InvalidRequest('DPoP proof JWT Replay detected'));
}
}
const unique = await ctx.oidc.provider.ReplayDetection.unique(
payload.iss,
payload.jti,
Expand Down
10 changes: 9 additions & 1 deletion lib/helpers/validate_dpop.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@ import instance from './weak_cache.js';
import * as base64url from './base64url.js';
import epochTime from './epoch_time.js';

const weakMap = new WeakMap();
export default async (ctx, accessToken) => {
if (weakMap.has(ctx)) {
return weakMap.get(ctx);
}

const {
features: { dPoP: dPoPConfig },
dPoPSigningAlgValues,
Expand Down Expand Up @@ -106,5 +111,8 @@ export default async (ctx, accessToken) => {

const thumbprint = await calculateJwkThumbprint(protectedHeader.jwk);

return { thumbprint, jti: payload.jti, iat: payload.iat };
const result = { thumbprint, jti: payload.jti, iat: payload.iat };
weakMap.set(ctx, result);

return result;
};

0 comments on commit ca0f999

Please sign in to comment.