Skip to content

Commit

Permalink
test: add a test for ensuring 30x non-conform behaviours can be worke…
Browse files Browse the repository at this point in the history
…d around
  • Loading branch information
panva committed Oct 23, 2024
1 parent b9a4f2f commit cd5e7d7
Showing 1 changed file with 162 additions and 0 deletions.
162 changes: 162 additions & 0 deletions test/issue-707.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
// see https://github.com/panva/openid-client/issues/707#issuecomment-2419779410

import test from 'ava'
import * as client from '../src/index.js'
import * as undici from 'undici'
import * as jose from 'jose'

test('30x on discoveries and jwks_uri can be worked around', async (t) => {
let agent = new undici.MockAgent()
agent.disableNetConnect()

const issuer = new URL('https://op.example.com/')
const kp = await client.randomDPoPKeyPair('ES256')

const mockAgent = agent.get(issuer.origin)

mockAgent
.intercept({
method: 'GET',
path: '/.well-known/openid-configuration',
})
.reply(302, new Uint8Array(), {
headers: {
location: 'https://op.example.com/not-conform-redirect',
},
})
.times(2)

mockAgent
.intercept({
method: 'GET',
path: '/jwks',
})
.reply(302, new Uint8Array(), {
headers: {
location: 'https://op.example.com/not-conform-jwks',
},
})
.times(2)

mockAgent
.intercept({
method: 'POST',
path: '/token',
})
.reply(
200,
{
access_token: 'foo',
token_type: 'bearer',
id_token: await new jose.SignJWT()
.setProtectedHeader({ alg: 'ES256' })
.setIssuer(issuer.href)
.setAudience('decoy')
.setIssuedAt()
.setExpirationTime('1m')
.setSubject('decoy')
.sign(kp.privateKey),
},
{
headers: {
'content-type': 'application/json',
},
},
)
.times(2)

mockAgent
.intercept({
method: 'GET',
path: '/not-conform-redirect',
})
.reply(
200,
{
issuer: issuer.href,
token_endpoint: 'https://op.example.com/token',
jwks_uri: 'https://op.example.com/jwks',
id_token_signing_alg_values_supported: ['ES256'],
},
{
headers: {
'content-type': 'application/json',
},
},
)

mockAgent
.intercept({
method: 'GET',
path: '/not-conform-jwks',
})
.reply(
200,
{
keys: [await jose.exportJWK(kp.publicKey)],
},
{
headers: {
'content-type': 'application/json',
},
},
)

const hit = new Set<string>()

let err = await t.throwsAsync(
client.discovery(issuer, 'decoy', 'decoy', undefined, {
// @ts-ignore
[client.customFetch](url, options) {
return undici.fetch(url, { ...options, dispatcher: agent })
},
}),
{
code: 'OAUTH_RESPONSE_IS_NOT_CONFORM',
message: 'unexpected HTTP response status code',
},
)

t.regex((err.cause as Response).url, /well-known/)

const config = await client.discovery(issuer, 'decoy', 'decoy', undefined, {
execute: [client.enableNonRepudiationChecks],
// @ts-ignore
[client.customFetch](url, options) {
if (url.includes('.well-known')) {
// @ts-expect-error
options.redirect = 'follow'
} else {
if (hit.has(url)) {
// @ts-expect-error
options.redirect = 'follow'
} else {
hit.add(url)
}
}
return undici.fetch(url, { ...options, dispatcher: agent })
},
})

err = await t.throwsAsync(
client.authorizationCodeGrant(
config,
new URL('https://rp.example.com/cb?code=foo'),
),
{
code: 'OAUTH_RESPONSE_IS_NOT_CONFORM',
message: 'unexpected HTTP response status code',
},
)

t.regex((err.cause as Response).url, /jwks/)

await t.notThrowsAsync(
client.authorizationCodeGrant(
config,
new URL('https://rp.example.com/cb?code=foo'),
),
)

t.notThrows(() => agent.assertNoPendingInterceptors())
})

0 comments on commit cd5e7d7

Please sign in to comment.