From 3eb165a425212a12cf9e48f899a999d32dd9ec86 Mon Sep 17 00:00:00 2001 From: Filip Skokan Date: Mon, 21 Nov 2022 12:53:50 +0100 Subject: [PATCH] fix: claims parameter encoding in issued request objects --- src/index.ts | 16 ++++++++++++++ tap/request_object.ts | 50 +++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 64 insertions(+), 2 deletions(-) diff --git a/src/index.ts b/src/index.ts index 935fcf62..54d45dd4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1157,6 +1157,22 @@ export async function issueRequestObject( claims.resource = resource } + if (parameters.has('claims')) { + const value = parameters.get('claims')! + if (value === '[object Object]') { + throw new OPE('"claims" parameter must be passed as a UTF-8 encoded JSON') + } + try { + claims.claims = JSON.parse(value) + } catch { + throw new OPE('failed to parse the "claims" parameter as JSON') + } + + if (!isJsonObject(claims.claims)) { + throw new OPE('"claims" parameter must be a top level object') + } + } + return jwt( { alg: determineJWSAlgorithm(key), diff --git a/tap/request_object.ts b/tap/request_object.ts index 4dc92431..0cd2d087 100644 --- a/tap/request_object.ts +++ b/tap/request_object.ts @@ -49,12 +49,58 @@ export default (QUnit: QUnit) => { { key: kp.privateKey }, ) - const { payload, protectedHeader } = await jose.jwtVerify(jwt, kp.publicKey) - t.propEqual(protectedHeader, { alg: 'ES256', typ: 'oauth-authz-req+jwt' }) + const { payload } = await jose.jwtVerify(jwt, kp.publicKey) const { resource } = payload t.propEqual(resource, ['urn:example:resource', 'urn:example:resource-2']) }) + test('issueRequestObject() - claims parameter', async (t) => { + const kp = await keys.ES256 + + await t.rejects( + lib.issueRequestObject(issuer, client, new URLSearchParams([['claims', {}]]), { + key: kp.privateKey, + }), + /must be passed as a UTF-8 encoded JSON/, + ) + + await t.rejects( + lib.issueRequestObject(issuer, client, new URLSearchParams([['claims', '"']]), { + key: kp.privateKey, + }), + /failed to parse the "claims" parameter as JSON/, + ) + + await t.rejects( + lib.issueRequestObject(issuer, client, new URLSearchParams([['claims', 'null']]), { + key: kp.privateKey, + }), + /parameter must be a top level object/, + ) + + const jwt = await lib.issueRequestObject( + issuer, + client, + new URLSearchParams([ + [ + 'claims', + JSON.stringify({ + userinfo: { nickname: null }, + id_token: { email: null }, + }), + ], + ]), + { key: kp.privateKey }, + ) + + const { payload } = await jose.jwtVerify(jwt, kp.publicKey) + const { claims } = payload + t.propEqual(claims, { + userinfo: { nickname: null }, + id_token: { email: null }, + }) + }) + test('issueRequestObject() signature kid', async (t) => { const kp = await keys.ES256 const jwt = await lib.issueRequestObject(issuer, client, new URLSearchParams(), {