Skip to content

Commit

Permalink
fix: normalize authorization_details and max_age in issueRequestObject
Browse files Browse the repository at this point in the history
  • Loading branch information
panva committed Feb 5, 2024
1 parent 787282a commit f8d267e
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 18 deletions.
45 changes: 35 additions & 10 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1600,19 +1600,44 @@ export async function issueRequestObject(
claims.resource = resource
}

let value = parameters.get('claims')
if (value) {
if (value === '[object Object]') {
throw new OPE('"claims" parameter must be passed as a UTF-8 encoded JSON')
{
let value = parameters.get('max_age')
if (value !== null) {
claims.max_age = parseInt(value, 10)

if (!Number.isFinite(claims.max_age)) {
throw new OPE('"max_age" parameter must be a number')
}
}
try {
claims.claims = JSON.parse(value)
} catch (cause) {
throw new OPE('failed to parse the "claims" parameter as JSON', { cause })
}

{
let value = parameters.get('claims')
if (value !== null) {
try {
claims.claims = JSON.parse(value)
} catch (cause) {
throw new OPE('failed to parse the "claims" parameter as JSON', { cause })
}

if (!isJsonObject(claims.claims)) {
throw new OPE('"claims" parameter must be a JSON with a top level object')
}
}
}

if (!isJsonObject(claims.claims)) {
throw new OPE('"claims" parameter must be a top level object')
{
let value = parameters.get('authorization_details')
if (value !== null) {
try {
claims.authorization_details = JSON.parse(value)
} catch (cause) {
throw new OPE('failed to parse the "authorization_details" parameter as JSON', { cause })
}

if (!Array.isArray(claims.authorization_details)) {
throw new OPE('"authorization_details" parameter must be a JSON with a top level array')
}
}
}

Expand Down
70 changes: 62 additions & 8 deletions tap/request_object.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,6 @@ export default (QUnit: QUnit) => {
test('issueRequestObject() claims parameter', async (t) => {
const kp = await keys.ES256

await t.rejects(
lib.issueRequestObject(issuer, client, new URLSearchParams([['claims', <string>{}]]), {
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,
Expand All @@ -79,7 +72,7 @@ export default (QUnit: QUnit) => {
lib.issueRequestObject(issuer, client, new URLSearchParams([['claims', 'null']]), {
key: kp.privateKey,
}),
/parameter must be a top level object/,
/parameter must be a JSON with a top level object/,
)

const jwt = await lib.issueRequestObject(
Expand All @@ -105,6 +98,67 @@ export default (QUnit: QUnit) => {
})
})

test('issueRequestObject() authorization_details parameter', async (t) => {
const kp = await keys.ES256

await t.rejects(
lib.issueRequestObject(
issuer,
client,
new URLSearchParams([['authorization_details', '"']]),
{
key: kp.privateKey,
},
),
/failed to parse the "authorization_details" parameter as JSON/,
)

await t.rejects(
lib.issueRequestObject(
issuer,
client,
new URLSearchParams([['authorization_details', 'null']]),
{
key: kp.privateKey,
},
),
/parameter must be a JSON with a top level array/,
)

const jwt = await lib.issueRequestObject(
issuer,
client,
new URLSearchParams([['authorization_details', JSON.stringify([{ type: 'foo' }])]]),
{ key: kp.privateKey },
)

const { payload } = await jose.jwtVerify(jwt, kp.publicKey)
const { authorization_details } = payload
t.propEqual(authorization_details, [{ type: 'foo' }])
})

test('issueRequestObject() max_age parameter', async (t) => {
const kp = await keys.ES256

await t.rejects(
lib.issueRequestObject(issuer, client, new URLSearchParams([['max_age', 'null']]), {
key: kp.privateKey,
}),
/parameter must be a number/,
)

const jwt = await lib.issueRequestObject(
issuer,
client,
new URLSearchParams([['max_age', '10']]),
{ key: kp.privateKey },
)

const { payload } = await jose.jwtVerify(jwt, kp.publicKey)
const { max_age } = payload
t.propEqual(max_age, 10)
})

test('issueRequestObject() signature kid', async (t) => {
const kp = await keys.ES256
const jwt = await lib.issueRequestObject(issuer, client, new URLSearchParams(), {
Expand Down

0 comments on commit f8d267e

Please sign in to comment.