undici-oidc-interceptor manages an OIDC access token and transparently sets the Authorization header on any
request that is going to a limited set of domains.
The token is automatically renewed after it expires. It supports both a refresh_token
and client_credentials grants.
npm i undici undici-oidc-interceptorconst { Agent } = require('undici')
const { createOidcInterceptor } = require('undici-oidc-interceptor')
const dispatcher = new Agent().compose(createOidcInterceptor({
// The paramerts for the cliend_credentials grant of OIDC
clientId: 'FILLME',
clientSecret: 'FILLME',
idpTokenUrl: 'https://your-idp.com/token',
// Set an array of status codes that the interceptor should refresh and
// retry the request on
retryOnStatusCodes: [401],
// The array of urls that this interceptor will be appending `Authorization` header
// for automatically
urls: ['FILLME'],
// OPTIONAL: an initial access token
accessToken: ''
}))const { Agent } = require('undici')
const { createOidcInterceptor } = require('undici-oidc-interceptor')
const dispatcher = new Agent().compose(createOidcInterceptor({
// Provide a refresh token so the interceptor can manage the access token
// The refresh token must include an issuer (`iss`)
refreshToken: '',
idpTokenUrl: 'https://your-idp.com/token',
clientId: 'FILLME',
// Set an array of status codes that the interceptor should refresh and
// retry the request on
retryOnStatusCodes: [401],
// The array of urls that this interceptor will be appending `Authorization` header
// for automatically
urls: [],
// OPTIONAL: an initial access token
accessToken: ''
}))const { Agent } = require('undici')
const { createOidcInterceptor } = require('undici-oidc-interceptor')
const dispatcher = new Agent().compose(createOidcInterceptor({
// Provide a refresh token so the interceptor can manage the access token
// The refresh token must include an issuer (`iss`)
refreshToken: '',
idpTokenUrl: 'https://your-idp.com/token',
clientId: 'FILLME',
// Set an array of status codes that the interceptor should refresh and
// retry the request on
retryOnStatusCodes: [401],
// OPTIONAL: a callback function, if return 'true' then this interceptor will include `Authorization` header
shouldAuthenticate: (opts) => opts.header['something'] === 'test',
// OPTIONAL: an initial access token
accessToken: ''
}))Note:
shouldAuthenticatehas higher priority than urls. Fallback to urls behavior when shouldAuthenticate is not provided
This interceptor uses the async-cache-dedupe package to cache access tokens. This improves efficiency by enabling token reuse across processes or instances and avoids unnecessary token refresh requests.
- Default: In-memory storage.
- Custom storage: You can provide your own backend (e.g., Redis) by supplying a compatible async-cache-dedupe configuration.
Example: Using Redis as the token store
const Redis = require('ioredis')
const { Agent } = require('undici')
const { createOidcInterceptor } = require('undici-oidc-interceptor')
const redisClient = new Redis()
const dispatcher = new Agent().compose(createOidcInterceptor({
...options,
tokenStore: {
name: 'test-cache',
ttl: 100,
storage: {
type: 'redis',
options: {
client: redisClient
}
}
}
}))If you want to customize the TTL for tokens based on the expiresIn value from the OIDC response, you can provide a custom function.
Example:
const Redis = require('ioredis')
const { Agent } = require('undici')
const { createOidcInterceptor } = require('undici-oidc-interceptor')
const redisClient = new Redis()
const dispatcher = new Agent().compose(createOidcInterceptor({
...options,
tokenStore: {
name: 'test-cache',
ttl: (tokenPayload) => tokenPayload.expiresIn * 80 / 100, // Sets token TTL to 80% of the OIDC expiry time
storage: {
type: 'redis',
options: {
client: redisClient
}
}
}
}))MIT