mirror of
https://github.com/danbulant/jose
synced 2026-05-19 04:18:52 +00:00
feat: optional headers options for createRemoteJWKSet (#397)
Co-authored-by: Filip Skokan <panva.ip@gmail.com>
This commit is contained in:
parent
c58c80ae98
commit
b4612f5d25
4 changed files with 34 additions and 5 deletions
|
|
@ -42,6 +42,11 @@ export interface RemoteJWKSetOptions {
|
|||
* runtime.
|
||||
*/
|
||||
agent?: any
|
||||
|
||||
/**
|
||||
* Optional headers to be sent with the HTTP request.
|
||||
*/
|
||||
headers?: Record<string, string>
|
||||
}
|
||||
|
||||
class RemoteJWKSet extends LocalJWKSet {
|
||||
|
|
@ -57,7 +62,7 @@ class RemoteJWKSet extends LocalJWKSet {
|
|||
|
||||
private _pendingFetch?: Promise<unknown>
|
||||
|
||||
private _options: Pick<RemoteJWKSetOptions, 'agent'>
|
||||
private _options: Pick<RemoteJWKSetOptions, 'agent' | 'headers'>
|
||||
|
||||
constructor(url: unknown, options?: RemoteJWKSetOptions) {
|
||||
super({ keys: [] })
|
||||
|
|
@ -68,7 +73,7 @@ class RemoteJWKSet extends LocalJWKSet {
|
|||
throw new TypeError('url must be an instance of URL')
|
||||
}
|
||||
this._url = new URL(url.href)
|
||||
this._options = { agent: options?.agent }
|
||||
this._options = { agent: options?.agent, headers: options?.headers }
|
||||
this._timeoutDuration =
|
||||
typeof options?.timeoutDuration === 'number' ? options?.timeoutDuration : 5000
|
||||
this._cooldownDuration =
|
||||
|
|
|
|||
|
|
@ -1,7 +1,13 @@
|
|||
import type { FetchFunction } from '../interfaces.d'
|
||||
import { JOSEError, JWKSTimeout } from '../../util/errors.js'
|
||||
|
||||
const fetchJwks: FetchFunction = async (url: URL, timeout: number) => {
|
||||
type AcceptedRequestOptions = Pick<RequestInit, 'headers'>
|
||||
|
||||
const fetchJwks: FetchFunction = async (
|
||||
url: URL,
|
||||
timeout: number,
|
||||
options: AcceptedRequestOptions,
|
||||
) => {
|
||||
let controller!: AbortController
|
||||
let id!: ReturnType<typeof setTimeout>
|
||||
let timedOut = false
|
||||
|
|
@ -16,6 +22,7 @@ const fetchJwks: FetchFunction = async (url: URL, timeout: number) => {
|
|||
const response = await fetch(url.href, {
|
||||
signal: controller ? controller.signal : undefined,
|
||||
redirect: 'manual',
|
||||
headers: options.headers,
|
||||
}).catch((err) => {
|
||||
if (timedOut) throw new JWKSTimeout()
|
||||
throw err
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import type { FetchFunction } from '../interfaces.d'
|
|||
import { JOSEError, JWKSTimeout } from '../../util/errors.js'
|
||||
import { concat, decoder } from '../../lib/buffer_utils.js'
|
||||
|
||||
type AcceptedRequestOptions = Pick<RequestOptions, 'agent'>
|
||||
type AcceptedRequestOptions = Pick<RequestOptions, 'agent' | 'headers'>
|
||||
|
||||
const fetchJwks: FetchFunction = async (
|
||||
url: URL,
|
||||
|
|
@ -27,10 +27,11 @@ const fetchJwks: FetchFunction = async (
|
|||
throw new TypeError('Unsupported URL protocol.')
|
||||
}
|
||||
|
||||
const { agent } = options
|
||||
const { agent, headers } = options
|
||||
const req = get(url.href, {
|
||||
agent,
|
||||
timeout,
|
||||
headers,
|
||||
})
|
||||
|
||||
const [response] = <[IncomingMessage]>(
|
||||
|
|
|
|||
|
|
@ -362,6 +362,22 @@ skipOnUndiciTestSerial('throws on invalid JWKSet', async (t) => {
|
|||
})
|
||||
})
|
||||
|
||||
skipOnUndiciTestSerial('can have headers configured', async (t) => {
|
||||
const scope = nock('https://as.example.com', {
|
||||
reqheaders: {
|
||||
'x-custom': 'foo',
|
||||
},
|
||||
})
|
||||
.get('/jwks')
|
||||
.once()
|
||||
.reply(200, 'null')
|
||||
|
||||
const url = new URL('https://as.example.com/jwks')
|
||||
const JWKS = createRemoteJWKSet(url, { headers: { 'x-custom': 'foo' } })
|
||||
await JWKS().catch(() => {})
|
||||
t.true(scope.isDone())
|
||||
})
|
||||
|
||||
skipOnUndiciTest('handles ENOTFOUND', async (t) => {
|
||||
nock.enableNetConnect()
|
||||
const url = new URL('https://op.example.com/jwks')
|
||||
|
|
|
|||
Loading…
Reference in a new issue