oauth4webapi
Version:
Low-Level OAuth 2 / OpenID Connect Client API for JavaScript Runtimes
1,383 lines (1,382 loc) • 109 kB
TypeScript
/**
* @ignore
*/
export type CryptoKey = Extract<Awaited<ReturnType<typeof crypto.subtle.generateKey>>, {
type: string;
}>;
export interface CryptoKeyPair {
privateKey: CryptoKey;
publicKey: CryptoKey;
}
/**
* JSON Object
*/
export type JsonObject = {
[Key in string]?: JsonValue;
};
/**
* JSON Array
*/
export type JsonArray = JsonValue[];
/**
* JSON Primitives
*/
export type JsonPrimitive = string | number | boolean | null;
/**
* JSON Values
*/
export type JsonValue = JsonPrimitive | JsonObject | JsonArray;
export interface ModifyAssertionFunction {
(
/**
* JWS Header to modify right before it is signed.
*/
header: Record<string, JsonValue | undefined>,
/**
* JWT Claims Set to modify right before it is signed.
*/
payload: Record<string, JsonValue | undefined>): void;
}
/**
* Interface to pass an asymmetric private key and, optionally, its associated JWK Key ID to be
* added as a `kid` JOSE Header Parameter.
*/
export interface PrivateKey {
/**
* An asymmetric private CryptoKey.
*
* Its algorithm must be compatible with a supported {@link JWSAlgorithm JWS Algorithm}.
*/
key: CryptoKey;
/**
* JWK Key ID to add to JOSE headers when this key is used. When not provided no `kid` (JWK Key
* ID) will be added to the JOSE Header.
*/
kid?: string;
}
/**
* JWS `alg` Algorithm identifiers from the
* {@link https://www.iana.org/assignments/jose/jose.xhtml#web-signature-encryption-algorithms JSON Web Signature and Encryption Algorithms IANA registry}
* for which Digital Signature validation is implemented.
*/
export type JWSAlgorithm = 'PS256' | 'ES256' | 'RS256' | 'Ed25519' | 'ES384' | 'PS384' | 'RS384' | 'ES512' | 'PS512' | 'RS512' | 'EdDSA';
export interface JWK {
readonly kty?: string;
readonly kid?: string;
readonly alg?: string;
readonly use?: string;
readonly key_ops?: string[];
readonly e?: string;
readonly n?: string;
readonly crv?: string;
readonly x?: string;
readonly y?: string;
readonly [parameter: string]: JsonValue | undefined;
}
/**
* By default the module only allows interactions with HTTPS endpoints. Setting this option to
* `true` removes that restriction.
*
* @deprecated To make it stand out as something you shouldn't use, possibly only for local
* development and testing against non-TLS secured environments.
*/
export declare const allowInsecureRequests: unique symbol;
/**
* Use to adjust the assumed current time. Positive and negative finite values representing seconds
* are allowed. Default is `0` (Date.now() + 0 seconds is used).
*
* @example
*
* When the local clock is mistakenly 1 hour in the past
*
* ```ts
* let client: oauth.Client = {
* client_id: 'abc4ba37-4ab8-49b5-99d4-9441ba35d428',
* // ... other metadata
* [oauth.clockSkew]: +(60 * 60),
* }
* ```
*
* @example
*
* When the local clock is mistakenly 1 hour in the future
*
* ```ts
* let client: oauth.Client = {
* client_id: 'abc4ba37-4ab8-49b5-99d4-9441ba35d428',
* // ... other metadata
* [oauth.clockSkew]: -(60 * 60),
* }
* ```
*/
export declare const clockSkew: unique symbol;
/**
* Use to set allowed clock tolerance when checking DateTime JWT Claims. Only positive finite values
* representing seconds are allowed. Default is `30` (30 seconds).
*
* @example
*
* Tolerate 30 seconds clock skew when validating JWT claims like exp or nbf.
*
* ```ts
* let client: oauth.Client = {
* client_id: 'abc4ba37-4ab8-49b5-99d4-9441ba35d428',
* // ... other metadata
* [oauth.clockTolerance]: 30,
* }
* ```
*/
export declare const clockTolerance: unique symbol;
/**
* When configured on an interface that extends {@link HttpRequestOptions}, this applies to `options`
* parameter for functions that may trigger HTTP requests, this replaces the use of global fetch. As
* a fetch replacement the arguments and expected return are the same as fetch.
*
* In theory any module that claims to be compatible with the Fetch API can be used but your mileage
* may vary. No workarounds to allow use of non-conform {@link !Response}s will be considered.
*
* If you only need to update the {@link !Request} properties you do not need to use a Fetch API
* module, just change what you need and pass it to globalThis.fetch just like this module would
* normally do.
*
* Its intended use cases are:
*
* - {@link !Request}/{@link !Response} tracing and logging
* - Custom caching strategies for responses of Authorization Server Metadata and JSON Web Key Set
* (JWKS) endpoints
* - Changing the {@link !Request} properties like headers, body, credentials, mode before it is passed
* to fetch
*
* Known caveats:
*
* - Expect Type-related issues when passing the inputs through to fetch-like modules, they hardly
* ever get their typings inline with actual fetch, you should `@ts-expect-error` them.
* - Returning self-constructed {@link !Response} instances prohibits AS/RS-signalled DPoP Nonce
* caching.
*
* @example
*
* Using [sindresorhus/ky](https://github.com/sindresorhus/ky) for retries and its hooks feature for
* logging outgoing requests and their responses.
*
* ```js
* import ky from 'ky'
*
* // example use
* await oauth.discoveryRequest(new URL('https://as.example.com'), {
* [oauth.customFetch]: (...args) =>
* ky(args[0], {
* ...args[1],
* hooks: {
* beforeRequest: [
* (request) => {
* logRequest(request)
* },
* ],
* beforeRetry: [
* ({ request, error, retryCount }) => {
* logRetry(request, error, retryCount)
* },
* ],
* afterResponse: [
* (request, _, response) => {
* logResponse(request, response)
* },
* ],
* },
* }),
* })
* ```
*
* @example
*
* Using [nodejs/undici](https://github.com/nodejs/undici) to detect and use HTTP proxies.
*
* ```ts
* import * as undici from 'undici'
*
* // see https://undici.nodejs.org/#/docs/api/EnvHttpProxyAgent
* let envHttpProxyAgent = new undici.EnvHttpProxyAgent()
*
* // example use
* await oauth.discoveryRequest(new URL('https://as.example.com'), {
* // @ts-ignore
* [oauth.customFetch](...args) {
* return undici.fetch(args[0], { ...args[1], dispatcher: envHttpProxyAgent }) // prettier-ignore
* },
* })
* ```
*
* @example
*
* Using [nodejs/undici](https://github.com/nodejs/undici) to automatically retry network errors.
*
* ```ts
* import * as undici from 'undici'
*
* // see https://undici.nodejs.org/#/docs/api/RetryAgent
* let retryAgent = new undici.RetryAgent(new undici.Agent(), {
* statusCodes: [],
* errorCodes: [
* 'ECONNRESET',
* 'ECONNREFUSED',
* 'ENOTFOUND',
* 'ENETDOWN',
* 'ENETUNREACH',
* 'EHOSTDOWN',
* 'UND_ERR_SOCKET',
* ],
* })
*
* // example use
* await oauth.discoveryRequest(new URL('https://as.example.com'), {
* // @ts-ignore
* [oauth.customFetch](...args) {
* return undici.fetch(args[0], { ...args[1], dispatcher: retryAgent }) // prettier-ignore
* },
* })
* ```
*
* @example
*
* Using [nodejs/undici](https://github.com/nodejs/undici) to mock responses in tests.
*
* ```ts
* import * as undici from 'undici'
*
* // see https://undici.nodejs.org/#/docs/api/MockAgent
* let mockAgent = new undici.MockAgent()
* mockAgent.disableNetConnect()
*
* // example use
* await oauth.discoveryRequest(new URL('https://as.example.com'), {
* // @ts-ignore
* [oauth.customFetch](...args) {
* return undici.fetch(args[0], { ...args[1], dispatcher: mockAgent }) // prettier-ignore
* },
* })
* ```
*/
export declare const customFetch: unique symbol;
/**
* Use to mutate JWT header and payload before they are signed. Its intended use is working around
* non-conform server behaviours, such as modifying JWT "aud" (audience) claims, or otherwise
* changing fixed claims used by this library.
*
* @example
*
* Changing the `alg: "Ed25519"` back to `alg: "EdDSA"`
*
* ```ts
* let as!: oauth.AuthorizationServer
* let client!: oauth.Client
* let parameters!: URLSearchParams
* let key!: oauth.CryptoKey | oauth.PrivateKey
* let keyPair!: oauth.CryptoKeyPair
*
* let remapEd25519: oauth.ModifyAssertionOptions = {
* [oauth.modifyAssertion]: (header, _payload) => {
* if (header.alg === 'Ed25519') {
* header.alg = 'EdDSA'
* }
* },
* }
*
* // For JAR
* oauth.issueRequestObject(as, client, parameters, key, remapEd25519)
*
* // For Private Key JWT
* oauth.PrivateKeyJwt(key, remapEd25519)
*
* // For DPoP
* oauth.DPoP(client, keyPair, remapEd25519)
* ```
*/
export declare const modifyAssertion: unique symbol;
/**
* Use to add support for decrypting JWEs the client encounters, namely
*
* - Encrypted ID Tokens returned by the Token Endpoint
* - Encrypted ID Tokens returned as part of FAPI 1.0 Advanced Detached Signature authorization
* responses
* - Encrypted JWT UserInfo responses
* - Encrypted JWT Introspection responses
* - Encrypted JARM Responses
*
* @example
*
* Decrypting JARM responses
*
* ```ts
* import * as jose from 'jose'
*
* let as!: oauth.AuthorizationServer
* let client!: oauth.Client
* let key!: oauth.CryptoKey
* let alg!: string
* let enc!: string
* let currentUrl!: URL
* let state!: string | undefined
*
* let decoder = new TextDecoder()
* let jweDecrypt: oauth.JweDecryptFunction = async (jwe) => {
* const { plaintext } = await jose
* .compactDecrypt(jwe, key, {
* keyManagementAlgorithms: [alg],
* contentEncryptionAlgorithms: [enc],
* })
* .catch((cause: unknown) => {
* throw new oauth.OperationProcessingError('decryption failed', { cause })
* })
*
* return decoder.decode(plaintext)
* }
*
* let params = await oauth.validateJwtAuthResponse(as, client, currentUrl, state, {
* [oauth.jweDecrypt]: jweDecrypt,
* })
* ```
*/
export declare const jweDecrypt: unique symbol;
/**
* > [!WARNING]\
* > This option has security implications that must be understood, assessed for applicability, and
* > accepted before use. It is critical that the JSON Web Key Set cache only be writable by your own
* > code.
*
* This option is intended for cloud computing runtimes that cannot keep an in memory cache between
* their code's invocations. Use in runtimes where an in memory cache between requests is available
* is not desirable.
*
* When configured on an interface that extends {@link JWKSCacheOptions}, this applies to `options`
* parameter for functions that may trigger HTTP requests to
* {@link AuthorizationServer.jwks_uri `as.jwks_uri`}, this allows the passed in object to:
*
* - Serve as an initial value for the JSON Web Key Set that the module would otherwise need to
* trigger an HTTP request for
* - Have the JSON Web Key Set the function optionally ended up triggering an HTTP request for
* assigned to it as properties
*
* The intended use pattern is:
*
* - Before executing a function with {@link JWKSCacheOptions} in its `options` parameter you pull the
* previously cached object from a low-latency key-value store offered by the cloud computing
* runtime it is executed on;
* - Default to an empty object `{}` instead when there's no previously cached value;
* - Pass it into the options interfaces that extend {@link JWKSCacheOptions};
* - Afterwards, update the key-value storage if the {@link ExportedJWKSCache.uat `uat`} property of
* the object has changed.
*
* @example
*
* ```ts
* let as!: oauth.AuthorizationServer
* let request!: Request
* let expectedAudience!: string
* let getPreviouslyCachedJWKS!: () => Promise<oauth.ExportedJWKSCache>
* let storeNewJWKScache!: (cache: oauth.ExportedJWKSCache) => Promise<void>
*
* // Load JSON Web Key Set cache
* let jwksCache: oauth.JWKSCacheInput = (await getPreviouslyCachedJWKS()) || {}
* let { uat } = jwksCache
*
* // Use JSON Web Key Set cache
* let accessTokenClaims = await oauth.validateJwtAccessToken(as, request, expectedAudience, {
* [oauth.jwksCache]: jwksCache,
* })
*
* if (uat !== jwksCache.uat) {
* // Update JSON Web Key Set cache
* await storeNewJWKScache(jwksCache)
* }
* ```
*/
export declare const jwksCache: unique symbol;
/**
* Authorization Server Metadata
*
* @group Authorization Server Metadata
*
* @see [IANA OAuth Authorization Server Metadata registry](https://www.iana.org/assignments/oauth-parameters/oauth-parameters.xhtml#authorization-server-metadata)
*/
export interface AuthorizationServer {
/**
* Authorization server's Issuer Identifier URL.
*/
readonly issuer: string;
/**
* URL of the authorization server's authorization endpoint.
*/
readonly authorization_endpoint?: string;
/**
* URL of the authorization server's token endpoint.
*/
readonly token_endpoint?: string;
/**
* URL of the authorization server's JWK Set document.
*/
readonly jwks_uri?: string;
/**
* URL of the authorization server's Dynamic Client Registration Endpoint.
*/
readonly registration_endpoint?: string;
/**
* JSON array containing a list of the `scope` values that this authorization server supports.
*/
readonly scopes_supported?: string[];
/**
* JSON array containing a list of the `response_type` values that this authorization server
* supports.
*/
readonly response_types_supported?: string[];
/**
* JSON array containing a list of the `response_mode` values that this authorization server
* supports.
*/
readonly response_modes_supported?: string[];
/**
* JSON array containing a list of the `grant_type` values that this authorization server
* supports.
*/
readonly grant_types_supported?: string[];
/**
* JSON array containing a list of client authentication methods supported by this token endpoint.
*/
readonly token_endpoint_auth_methods_supported?: string[];
/**
* JSON array containing a list of the JWS signing algorithms supported by the token endpoint for
* the signature on the JWT used to authenticate the client at the token endpoint.
*/
readonly token_endpoint_auth_signing_alg_values_supported?: string[];
/**
* URL of a page containing human-readable information that developers might want or need to know
* when using the authorization server.
*/
readonly service_documentation?: string;
/**
* Languages and scripts supported for the user interface, represented as a JSON array of language
* tag values from RFC 5646.
*/
readonly ui_locales_supported?: string[];
/**
* URL that the authorization server provides to the person registering the client to read about
* the authorization server's requirements on how the client can use the data provided by the
* authorization server.
*/
readonly op_policy_uri?: string;
/**
* URL that the authorization server provides to the person registering the client to read about
* the authorization server's terms of service.
*/
readonly op_tos_uri?: string;
/**
* URL of the authorization server's revocation endpoint.
*/
readonly revocation_endpoint?: string;
/**
* JSON array containing a list of client authentication methods supported by this revocation
* endpoint.
*/
readonly revocation_endpoint_auth_methods_supported?: string[];
/**
* JSON array containing a list of the JWS signing algorithms supported by the revocation endpoint
* for the signature on the JWT used to authenticate the client at the revocation endpoint.
*/
readonly revocation_endpoint_auth_signing_alg_values_supported?: string[];
/**
* URL of the authorization server's introspection endpoint.
*/
readonly introspection_endpoint?: string;
/**
* JSON array containing a list of client authentication methods supported by this introspection
* endpoint.
*/
readonly introspection_endpoint_auth_methods_supported?: string[];
/**
* JSON array containing a list of the JWS signing algorithms supported by the introspection
* endpoint for the signature on the JWT used to authenticate the client at the introspection
* endpoint.
*/
readonly introspection_endpoint_auth_signing_alg_values_supported?: string[];
/**
* PKCE code challenge methods supported by this authorization server.
*/
readonly code_challenge_methods_supported?: string[];
/**
* Signed JWT containing metadata values about the authorization server as claims.
*/
readonly signed_metadata?: string;
/**
* URL of the authorization server's device authorization endpoint.
*/
readonly device_authorization_endpoint?: string;
/**
* Indicates authorization server support for mutual-TLS client certificate-bound access tokens.
*/
readonly tls_client_certificate_bound_access_tokens?: boolean;
/**
* JSON object containing alternative authorization server endpoints, which a client intending to
* do mutual TLS will use in preference to the conventional endpoints.
*/
readonly mtls_endpoint_aliases?: MTLSEndpointAliases;
/**
* URL of the authorization server's UserInfo Endpoint.
*/
readonly userinfo_endpoint?: string;
/**
* JSON array containing a list of the Authentication Context Class References that this
* authorization server supports.
*/
readonly acr_values_supported?: string[];
/**
* JSON array containing a list of the Subject Identifier types that this authorization server
* supports.
*/
readonly subject_types_supported?: string[];
/**
* JSON array containing a list of the JWS `alg` values supported by the authorization server for
* the ID Token.
*/
readonly id_token_signing_alg_values_supported?: string[];
/**
* JSON array containing a list of the JWE `alg` values supported by the authorization server for
* the ID Token.
*/
readonly id_token_encryption_alg_values_supported?: string[];
/**
* JSON array containing a list of the JWE `enc` values supported by the authorization server for
* the ID Token.
*/
readonly id_token_encryption_enc_values_supported?: string[];
/**
* JSON array containing a list of the JWS `alg` values supported by the UserInfo Endpoint.
*/
readonly userinfo_signing_alg_values_supported?: string[];
/**
* JSON array containing a list of the JWE `alg` values supported by the UserInfo Endpoint.
*/
readonly userinfo_encryption_alg_values_supported?: string[];
/**
* JSON array containing a list of the JWE `enc` values supported by the UserInfo Endpoint.
*/
readonly userinfo_encryption_enc_values_supported?: string[];
/**
* JSON array containing a list of the JWS `alg` values supported by the authorization server for
* Request Objects.
*/
readonly request_object_signing_alg_values_supported?: string[];
/**
* JSON array containing a list of the JWE `alg` values supported by the authorization server for
* Request Objects.
*/
readonly request_object_encryption_alg_values_supported?: string[];
/**
* JSON array containing a list of the JWE `enc` values supported by the authorization server for
* Request Objects.
*/
readonly request_object_encryption_enc_values_supported?: string[];
/**
* JSON array containing a list of the `display` parameter values that the authorization server
* supports.
*/
readonly display_values_supported?: string[];
/**
* JSON array containing a list of the Claim Types that the authorization server supports.
*/
readonly claim_types_supported?: string[];
/**
* JSON array containing a list of the Claim Names of the Claims that the authorization server MAY
* be able to supply values for.
*/
readonly claims_supported?: string[];
/**
* Languages and scripts supported for values in Claims being returned, represented as a JSON
* array of RFC 5646 language tag values.
*/
readonly claims_locales_supported?: string[];
/**
* Boolean value specifying whether the authorization server supports use of the `claims`
* parameter.
*/
readonly claims_parameter_supported?: boolean;
/**
* Boolean value specifying whether the authorization server supports use of the `request`
* parameter.
*/
readonly request_parameter_supported?: boolean;
/**
* Boolean value specifying whether the authorization server supports use of the `request_uri`
* parameter.
*/
readonly request_uri_parameter_supported?: boolean;
/**
* Boolean value specifying whether the authorization server requires any `request_uri` values
* used to be pre-registered.
*/
readonly require_request_uri_registration?: boolean;
/**
* Indicates where authorization request needs to be protected as Request Object and provided
* through either `request` or `request_uri` parameter.
*/
readonly require_signed_request_object?: boolean;
/**
* URL of the authorization server's pushed authorization request endpoint.
*/
readonly pushed_authorization_request_endpoint?: string;
/**
* Indicates whether the authorization server accepts authorization requests only via PAR.
*/
readonly require_pushed_authorization_requests?: boolean;
/**
* JSON array containing a list of algorithms supported by the authorization server for
* introspection response signing.
*/
readonly introspection_signing_alg_values_supported?: string[];
/**
* JSON array containing a list of algorithms supported by the authorization server for
* introspection response content key encryption (`alg` value).
*/
readonly introspection_encryption_alg_values_supported?: string[];
/**
* JSON array containing a list of algorithms supported by the authorization server for
* introspection response content encryption (`enc` value).
*/
readonly introspection_encryption_enc_values_supported?: string[];
/**
* Boolean value indicating whether the authorization server provides the `iss` parameter in the
* authorization response.
*/
readonly authorization_response_iss_parameter_supported?: boolean;
/**
* JSON array containing a list of algorithms supported by the authorization server for
* introspection response signing.
*/
readonly authorization_signing_alg_values_supported?: string[];
/**
* JSON array containing a list of algorithms supported by the authorization server for
* introspection response encryption (`alg` value).
*/
readonly authorization_encryption_alg_values_supported?: string[];
/**
* JSON array containing a list of algorithms supported by the authorization server for
* introspection response encryption (`enc` value).
*/
readonly authorization_encryption_enc_values_supported?: string[];
/**
* CIBA Backchannel Authentication Endpoint.
*/
readonly backchannel_authentication_endpoint?: string;
/**
* JSON array containing a list of the JWS signing algorithms supported for validation of signed
* CIBA authentication requests.
*/
readonly backchannel_authentication_request_signing_alg_values_supported?: string[];
/**
* Supported CIBA authentication result delivery modes.
*/
readonly backchannel_token_delivery_modes_supported?: string[];
/**
* Indicates whether the authorization server supports the use of the CIBA `user_code` parameter.
*/
readonly backchannel_user_code_parameter_supported?: boolean;
/**
* URL of an authorization server iframe that supports cross-origin communications for session
* state information with the RP Client, using the HTML5 postMessage API.
*/
readonly check_session_iframe?: string;
/**
* JSON array containing a list of the JWS algorithms supported for DPoP Proof JWTs.
*/
readonly dpop_signing_alg_values_supported?: string[];
/**
* URL at the authorization server to which an RP can perform a redirect to request that the
* End-User be logged out at the authorization server.
*/
readonly end_session_endpoint?: string;
/**
* Boolean value specifying whether the authorization server can pass `iss` (issuer) and `sid`
* (session ID) query parameters to identify the RP session with the authorization server when the
* `frontchannel_logout_uri` is used.
*/
readonly frontchannel_logout_session_supported?: boolean;
/**
* Boolean value specifying whether the authorization server supports HTTP-based logout.
*/
readonly frontchannel_logout_supported?: boolean;
/**
* Boolean value specifying whether the authorization server can pass a `sid` (session ID) Claim
* in the Logout Token to identify the RP session with the OP.
*/
readonly backchannel_logout_session_supported?: boolean;
/**
* Boolean value specifying whether the authorization server supports back-channel logout.
*/
readonly backchannel_logout_supported?: boolean;
/**
* JSON array containing a list of resource identifiers for OAuth protected resources.
*/
readonly protected_resources?: string[];
readonly [metadata: string]: JsonValue | undefined;
}
export interface MTLSEndpointAliases extends Pick<AuthorizationServer, 'backchannel_authentication_endpoint' | 'device_authorization_endpoint' | 'introspection_endpoint' | 'pushed_authorization_request_endpoint' | 'revocation_endpoint' | 'token_endpoint' | 'userinfo_endpoint'> {
readonly [metadata: string]: string | undefined;
}
/**
* Recognized Client Metadata that have an effect on the exposed functionality.
*
* @see [IANA OAuth Client Registration Metadata registry](https://www.iana.org/assignments/oauth-parameters/oauth-parameters.xhtml#client-metadata)
*/
export interface Client {
/**
* Client identifier.
*/
client_id: string;
/**
* JWS `alg` algorithm required for signing the ID Token issued to this Client. When not
* configured the default is to allow only algorithms listed in
* {@link AuthorizationServer.id_token_signing_alg_values_supported `as.id_token_signing_alg_values_supported`}
* and fall back to `RS256` when the authorization server metadata is not set.
*/
id_token_signed_response_alg?: string;
/**
* JWS `alg` algorithm required for signing authorization responses. When not configured the
* default is to allow only algorithms listed in
* {@link AuthorizationServer.authorization_signing_alg_values_supported `as.authorization_signing_alg_values_supported`}
* and fall back to `RS256` when the authorization server metadata is not set.
*/
authorization_signed_response_alg?: string;
/**
* Boolean value specifying whether the {@link IDToken.auth_time `auth_time`} Claim in the ID Token
* is REQUIRED. Default is `false`.
*/
require_auth_time?: boolean;
/**
* JWS `alg` algorithm REQUIRED for signing UserInfo Responses. When not configured the default is
* to allow only algorithms listed in
* {@link AuthorizationServer.userinfo_signing_alg_values_supported `as.userinfo_signing_alg_values_supported`}
* and fail otherwise.
*/
userinfo_signed_response_alg?: string;
/**
* JWS `alg` algorithm REQUIRED for signed introspection responses. When not configured the
* default is to allow only algorithms listed in
* {@link AuthorizationServer.introspection_signing_alg_values_supported `as.introspection_signing_alg_values_supported`}
* and fall back to `RS256` when the authorization server metadata is not set.
*/
introspection_signed_response_alg?: string;
/**
* Default Maximum Authentication Age.
*/
default_max_age?: number;
/**
* Indicates the requirement for a client to use mutual TLS endpoint aliases defined by the AS
* where present. Default is `false`.
*
* When combined with {@link customFetch} (to use a Fetch API implementation that supports client
* certificates) this can be used to target security profiles that utilize Mutual-TLS for either
* client authentication or sender constraining.
*
* @example
*
* (Node.js) Using [nodejs/undici](https://github.com/nodejs/undici) for Mutual-TLS Client
* Authentication and Certificate-Bound Access Tokens support.
*
* ```ts
* import * as undici from 'undici'
*
* let as!: oauth.AuthorizationServer
* let client!: oauth.Client & { use_mtls_endpoint_aliases: true }
* let params!: URLSearchParams
* let key!: string // PEM-encoded key
* let cert!: string // PEM-encoded certificate
*
* let clientAuth = oauth.TlsClientAuth()
* let agent = new undici.Agent({ connect: { key, cert } })
*
* let response = await oauth.pushedAuthorizationRequest(as, client, clientAuth, params, {
* // @ts-ignore
* [oauth.customFetch]: (...args) =>
* undici.fetch(args[0], { ...args[1], dispatcher: agent }),
* })
* ```
*
* @example
*
* (Deno) Using Deno.createHttpClient API for Mutual-TLS Client Authentication and
* Certificate-Bound Access Tokens support.
*
* ```ts
* let as!: oauth.AuthorizationServer
* let client!: oauth.Client & { use_mtls_endpoint_aliases: true }
* let params!: URLSearchParams
* let key!: string // PEM-encoded key
* let cert!: string // PEM-encoded certificate
*
* let clientAuth = oauth.TlsClientAuth()
* // @ts-ignore
* let agent = Deno.createHttpClient({ key, cert })
*
* let response = await oauth.pushedAuthorizationRequest(as, client, clientAuth, params, {
* // @ts-ignore
* [oauth.customFetch]: (...args) => fetch(args[0], { ...args[1], client: agent }),
* })
* ```
*
* @see [RFC 8705 - OAuth 2.0 Mutual-TLS Client Authentication and Certificate-Bound Access Tokens](https://www.rfc-editor.org/rfc/rfc8705.html)
*/
use_mtls_endpoint_aliases?: boolean;
/**
* See {@link clockSkew}.
*/
[clockSkew]?: number;
/**
* See {@link clockTolerance}.
*/
[clockTolerance]?: number;
[metadata: string]: JsonValue | undefined;
}
/**
* @group Errors
*/
export declare class UnsupportedOperationError extends Error {
code: string;
/**
* @ignore
*/
constructor(message: string, options?: {
cause?: unknown;
});
}
/**
* @group Errors
*/
export declare class OperationProcessingError extends Error {
code?: string;
/**
* @ignore
*/
constructor(message: string, options?: {
cause?: unknown;
code?: string;
});
}
export interface JWKSCacheOptions {
/**
* See {@link jwksCache}.
*/
[jwksCache]?: JWKSCacheInput;
}
export interface CustomFetchOptions<Method, BodyType = undefined> {
/**
* The request body content to send to the server
*/
body: BodyType;
/**
* HTTP Headers
*/
headers: Record<string, string>;
/**
* The {@link https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods request method}
*/
method: Method;
/**
* See {@link !Request.redirect}
*/
redirect: 'manual';
/**
* Depending on whether {@link HttpRequestOptions.signal} was used, if so, it is the value passed,
* otherwise undefined
*/
signal?: AbortSignal;
}
export interface HttpRequestOptions<Method, BodyType = undefined> {
/**
* An AbortSignal instance, or a factory returning one, to abort the HTTP request(s) triggered by
* this function's invocation.
*
* @example
*
* A 5000ms timeout AbortSignal for every request
*
* ```js
* let signal = () => AbortSignal.timeout(5_000) // Note: AbortSignal.timeout may not yet be available in all runtimes.
* ```
*/
signal?: (() => AbortSignal) | AbortSignal;
/**
* Headers to additionally send with the HTTP request(s) triggered by this function's invocation.
*/
headers?: [string, string][] | Record<string, string> | Headers;
/**
* See {@link customFetch}.
*/
[customFetch]?: (
/**
* URL the request is being made sent to {@link !fetch} as the `resource` argument
*/
url: string,
/**
* Options otherwise sent to {@link !fetch} as the `options` argument
*/
options: CustomFetchOptions<Method, BodyType>) => Promise<Response>;
/**
* See {@link allowInsecureRequests}.
*
* @deprecated
*/
[allowInsecureRequests]?: boolean;
}
export interface DiscoveryRequestOptions extends HttpRequestOptions<'GET'> {
/**
* The issuer transformation algorithm to use.
*/
algorithm?: 'oidc' | 'oauth2';
}
/**
* Performs an authorization server metadata discovery using one of two
* {@link DiscoveryRequestOptions.algorithm transformation algorithms} applied to the
* `issuerIdentifier` argument.
*
* - `oidc` (default) as defined by OpenID Connect Discovery 1.0.
* - `oauth2` as defined by RFC 8414.
*
* @param issuerIdentifier Issuer Identifier to resolve the well-known discovery URI for.
*
* @returns Resolves with a {@link !Response} to then invoke {@link processDiscoveryResponse} with
*
* @group Authorization Server Metadata
* @group OpenID Connect (OIDC) Discovery
*
* @see [RFC 8414 - OAuth 2.0 Authorization Server Metadata](https://www.rfc-editor.org/rfc/rfc8414.html#section-3)
* @see [OpenID Connect Discovery 1.0](https://openid.net/specs/openid-connect-discovery-1_0-errata2.html#ProviderConfig)
*/
export declare function discoveryRequest(issuerIdentifier: URL, options?: DiscoveryRequestOptions): Promise<Response>;
/**
* Validates {@link !Response} instance to be one coming from the authorization server's well-known
* discovery endpoint.
*
* @param expectedIssuerIdentifier Expected Issuer Identifier value.
* @param response Resolved value from {@link discoveryRequest}.
*
* @returns Resolves with the discovered Authorization Server Metadata.
*
* @group Authorization Server Metadata
* @group OpenID Connect (OIDC) Discovery
*
* @see [RFC 8414 - OAuth 2.0 Authorization Server Metadata](https://www.rfc-editor.org/rfc/rfc8414.html#section-3)
* @see [OpenID Connect Discovery 1.0](https://openid.net/specs/openid-connect-discovery-1_0-errata2.html#ProviderConfig)
*/
export declare function processDiscoveryResponse(expectedIssuerIdentifier: URL, response: Response): Promise<AuthorizationServer>;
/**
* Generate random `code_verifier` value.
*
* @group Utilities
* @group Authorization Code Grant
* @group Authorization Code Grant w/ OpenID Connect (OIDC)
* @group Proof Key for Code Exchange (PKCE)
*
* @see [RFC 7636 - Proof Key for Code Exchange (PKCE)](https://www.rfc-editor.org/rfc/rfc7636.html#section-4)
*/
export declare function generateRandomCodeVerifier(): string;
/**
* Generate random `state` value.
*
* @group Utilities
*
* @see [RFC 6749 - The OAuth 2.0 Authorization Framework](https://www.rfc-editor.org/rfc/rfc6749.html#section-4.1.1)
*/
export declare function generateRandomState(): string;
/**
* Generate random `nonce` value.
*
* @group Utilities
*
* @see [OpenID Connect Core 1.0](https://openid.net/specs/openid-connect-core-1_0-errata2.html#IDToken)
*/
export declare function generateRandomNonce(): string;
/**
* Calculates the PKCE `code_challenge` value to send with an authorization request using the S256
* PKCE Code Challenge Method transformation.
*
* @param codeVerifier `code_verifier` value generated e.g. from {@link generateRandomCodeVerifier}.
*
* @group Authorization Code Grant
* @group Authorization Code Grant w/ OpenID Connect (OIDC)
* @group Proof Key for Code Exchange (PKCE)
*
* @see [RFC 7636 - Proof Key for Code Exchange (PKCE)](https://www.rfc-editor.org/rfc/rfc7636.html#section-4)
*/
export declare function calculatePKCECodeChallenge(codeVerifier: string): Promise<string>;
export interface DPoPRequestOptions {
/**
* DPoP handle, obtained from {@link DPoP}
*/
DPoP?: DPoPHandle;
}
export interface PushedAuthorizationRequestOptions extends HttpRequestOptions<'POST', URLSearchParams>, DPoPRequestOptions {
}
/**
* Implementation of the Client's Authentication Method at the Authorization Server.
*
* @see {@link ClientSecretPost}
* @see {@link ClientSecretBasic}
* @see {@link PrivateKeyJwt}
* @see {@link None}
* @see {@link TlsClientAuth}
* @see [OAuth Token Endpoint Authentication Methods](https://www.iana.org/assignments/oauth-parameters/oauth-parameters.xhtml#token-endpoint-auth-method)
*/
export type ClientAuth = (as: AuthorizationServer, client: Client, body: URLSearchParams, headers: Headers) => void | Promise<void>;
/**
* **`client_secret_post`** uses the HTTP request body to send `client_id` and `client_secret` as
* `application/x-www-form-urlencoded` body parameters
*
* @example
*
* ```ts
* let clientSecret!: string
*
* let clientAuth = oauth.ClientSecretPost(clientSecret)
* ```
*
* @param clientSecret
*
* @group Client Authentication
*
* @see [OAuth Token Endpoint Authentication Methods](https://www.iana.org/assignments/oauth-parameters/oauth-parameters.xhtml#token-endpoint-auth-method)
* @see [RFC 6749 - The OAuth 2.0 Authorization Framework](https://www.rfc-editor.org/rfc/rfc6749.html#section-2.3)
* @see [OpenID Connect Core 1.0](https://openid.net/specs/openid-connect-core-1_0-errata2.html#ClientAuthentication)
*/
export declare function ClientSecretPost(clientSecret: string): ClientAuth;
/**
* **`client_secret_basic`** uses the HTTP `Basic` authentication scheme to send `client_id` and
* `client_secret` in an `Authorization` HTTP Header.
*
* @example
*
* ```ts
* let clientSecret!: string
*
* let clientAuth = oauth.ClientSecretBasic(clientSecret)
* ```
*
* @param clientSecret
*
* @group Client Authentication
*
* @see [OAuth Token Endpoint Authentication Methods](https://www.iana.org/assignments/oauth-parameters/oauth-parameters.xhtml#token-endpoint-auth-method)
* @see [RFC 6749 - The OAuth 2.0 Authorization Framework](https://www.rfc-editor.org/rfc/rfc6749.html#section-2.3)
* @see [OpenID Connect Core 1.0](https://openid.net/specs/openid-connect-core-1_0-errata2.html#ClientAuthentication)
*/
export declare function ClientSecretBasic(clientSecret: string): ClientAuth;
export interface ModifyAssertionOptions {
/**
* Use to modify a JWT assertion payload or header right before it is signed.
*
* @see {@link modifyAssertion}
*/
[modifyAssertion]?: ModifyAssertionFunction;
}
/**
* **`private_key_jwt`** uses the HTTP request body to send `client_id`, `client_assertion_type`,
* and `client_assertion` as `application/x-www-form-urlencoded` body parameters. Digital signature
* is used for the assertion's authenticity and integrity.
*
* @example
*
* ```ts
* let key!: oauth.CryptoKey | oauth.PrivateKey
*
* let clientAuth = oauth.PrivateKeyJwt(key)
* ```
*
* @param clientPrivateKey
*
* @group Client Authentication
*
* @see [OAuth Token Endpoint Authentication Methods](https://www.iana.org/assignments/oauth-parameters/oauth-parameters.xhtml#token-endpoint-auth-method)
* @see [OpenID Connect Core 1.0](https://openid.net/specs/openid-connect-core-1_0-errata2.html#ClientAuthentication)
*/
export declare function PrivateKeyJwt(clientPrivateKey: CryptoKey | PrivateKey, options?: ModifyAssertionOptions): ClientAuth;
/**
* **`client_secret_jwt`** uses the HTTP request body to send `client_id`, `client_assertion_type`,
* and `client_assertion` as `application/x-www-form-urlencoded` body parameters. HMAC is used for
* the assertion's authenticity and integrity.
*
* @example
*
* ```ts
* let clientSecret!: string
*
* let clientAuth = oauth.ClientSecretJwt(clientSecret)
* ```
*
* @param clientSecret
* @param options
*
* @group Client Authentication
*
* @see [OAuth Token Endpoint Authentication Methods](https://www.iana.org/assignments/oauth-parameters/oauth-parameters.xhtml#token-endpoint-auth-method)
* @see [OpenID Connect Core 1.0](https://openid.net/specs/openid-connect-core-1_0-errata2.html#ClientAuthentication)
*/
export declare function ClientSecretJwt(clientSecret: string, options?: ModifyAssertionOptions): ClientAuth;
/**
* **`none`** (public client) uses the HTTP request body to send only `client_id` as
* `application/x-www-form-urlencoded` body parameter.
*
* ```ts
* let clientAuth = oauth.None()
* ```
*
* @group Client Authentication
*
* @see [OAuth Token Endpoint Authentication Methods](https://www.iana.org/assignments/oauth-parameters/oauth-parameters.xhtml#token-endpoint-auth-method)
* @see [OpenID Connect Core 1.0](https://openid.net/specs/openid-connect-core-1_0-errata2.html#ClientAuthentication)
*/
export declare function None(): ClientAuth;
/**
* **`tls_client_auth`** uses the HTTP request body to send only `client_id` as
* `application/x-www-form-urlencoded` body parameter and the mTLS key and certificate is configured
* through {@link customFetch}.
*
* ```ts
* let clientAuth = oauth.TlsClientAuth()
* ```
*
* @group Client Authentication
*
* @see [OAuth Token Endpoint Authentication Methods](https://www.iana.org/assignments/oauth-parameters/oauth-parameters.xhtml#token-endpoint-auth-method)
* @see [RFC 8705 - OAuth 2.0 Mutual-TLS Client Authentication (PKI Mutual-TLS Method)](https://www.rfc-editor.org/rfc/rfc8705.html#name-pki-mutual-tls-method)
*/
export declare function TlsClientAuth(): ClientAuth;
/**
* Generates a signed JWT-Secured Authorization Request (JAR).
*
* @param as Authorization Server Metadata.
* @param client Client Metadata.
* @param privateKey Private key to sign the Request Object with.
*
* @group Authorization Code Grant
* @group Authorization Code Grant w/ OpenID Connect (OIDC)
* @group JWT-Secured Authorization Request (JAR)
*
* @see [RFC 9101 - The OAuth 2.0 Authorization Framework: JWT-Secured Authorization Request (JAR)](https://www.rfc-editor.org/rfc/rfc9101.html#name-request-object-2)
*/
export declare function issueRequestObject(as: AuthorizationServer, client: Client, parameters: URLSearchParams | Record<string, string> | string[][], privateKey: CryptoKey | PrivateKey, options?: ModifyAssertionOptions): Promise<string>;
/**
* @ignore
*/
export declare function checkProtocol(url: URL, enforceHttps: boolean | undefined): void;
/**
* Performs a Pushed Authorization Request at the
* {@link AuthorizationServer.pushed_authorization_request_endpoint `as.pushed_authorization_request_endpoint`}.
*
* @param as Authorization Server Metadata.
* @param client Client Metadata.
* @param clientAuthentication Client Authentication Method.
* @param parameters Authorization Request parameters.
*
* @returns Resolves with a {@link !Response} to then invoke
* {@link processPushedAuthorizationResponse} with
*
* @group Pushed Authorization Requests (PAR)
*
* @see [RFC 9126 - OAuth 2.0 Pushed Authorization Requests (PAR)](https://www.rfc-editor.org/rfc/rfc9126.html#name-pushed-authorization-reques)
* @see [RFC 9449 - OAuth 2.0 Demonstrating Proof-of-Possession at the Application Layer (DPoP)](https://www.rfc-editor.org/rfc/rfc9449.html#name-dpop-with-pushed-authorizat)
*/
export declare function pushedAuthorizationRequest(as: AuthorizationServer, client: Client, clientAuthentication: ClientAuth, parameters: URLSearchParams | Record<string, string> | string[][], options?: PushedAuthorizationRequestOptions): Promise<Response>;
/**
* DPoP handle, obtained from {@link DPoP}
*/
export interface DPoPHandle {
/**
* Calculates the JWK Thumbprint of the DPoP public key using the SHA-256 hash function for use as
* the optional `dpop_jkt` authorization request parameter.
*
* @see [RFC 9449 - OAuth 2.0 Demonstrating Proof-of-Possession at the Application Layer (DPoP)](https://www.rfc-editor.org/rfc/rfc9449.html#name-authorization-code-binding-)
*/
calculateThumbprint(): Promise<string>;
}
/**
* Used to determine if a rejected error indicates the need to retry the request due to an
* expired/missing nonce.
*
* @group DPoP
*/
export declare function isDPoPNonceError(err: unknown): boolean;
/**
* Returns a wrapper / handle around a {@link CryptoKeyPair} that is used for negotiating and proving
* proof-of-possession to sender-constrain OAuth 2.0 tokens via DPoP at the Authorization Server and
* Resource Server.
*
* This wrapper / handle also keeps track of server-issued nonces, allowing requests to be retried
* with a fresh nonce when the server indicates the need to use one. {@link isDPoPNonceError} can be
* used to determine if a rejected error indicates the need to retry the request due to an
* expired/missing nonce.
*
* @example
*
* ```ts
* let client!: oauth.Client
* let keyPair!: oauth.CryptoKeyPair
*
* let DPoP = oauth.DPoP(client, keyPair)
* ```
*
* @param keyPair Public/private key pair to sign the DPoP Proof JWT with
*
* @group DPoP
*
* @see {@link https://www.rfc-editor.org/rfc/rfc9449.html RFC 9449 - OAuth 2.0 Demonstrating Proof of Possession (DPoP)}
*/
export declare function DPoP(client: Pick<Client, typeof clockSkew>, keyPair: CryptoKeyPair, options?: ModifyAssertionOptions): DPoPHandle;
export interface PushedAuthorizationResponse {
readonly request_uri: string;
readonly expires_in: number;
readonly [parameter: string]: JsonValue | undefined;
}
export interface OAuth2Error {
readonly error: string;
readonly error_description?: string;
readonly error_uri?: string;
readonly algs?: string;
readonly scope?: string;
readonly [parameter: string]: JsonValue | undefined;
}
/**
* Throw when a server responds with an "OAuth-style" error JSON body
*
* @example
*
* ```http
* HTTP/1.1 400 Bad Request
* Content-Type: application/json;charset=UTF-8
* Cache-Control: no-store
* Pragma: no-cache
*
* {
* "error": "invalid_request"
* }
* ```
*
* @group Errors
*/
export declare class ResponseBodyError extends Error {
/**
* The parsed JSON response body
*/
cause: Record<string, JsonValue | undefined>;
code: typeof RESPONSE_BODY_ERROR;
/**
* Error code given in the JSON response
*/
error: string;
/**
* HTTP Status Code of the response
*/
status: number;
/**
* Human-readable text providing additional information, used to assist the developer in
* understanding the error that occurred, given in the JSON response
*/
error_description?: string;
/**
* The "OAuth-style" error {@link !Response}, its {@link !Response.bodyUsed} is `true` and the JSON
* body is available in {@link ResponseBodyError.cause}
*/
response: Response;
/**
* @ignore
*/
constructor(message: string, options: {
cause: OAuth2Error;
response: Response;
});
}
/**
* Thrown when OAuth 2.0 Authorization Error Response is encountered.
*
* @example
*
* ```http
* HTTP/1.1 302 Found
* Location: https://client.example.com/cb?error=access_denied&state=xyz
* ```
*
* @group Errors
*/
export declare class AuthorizationResponseError extends Error {
/**
* Authorization Response parameters as {@link !URLSearchParams}
*/
cause: URLSearchParams;
code: typeof AUTHORIZATION_RESPONSE_ERROR;
/**
* Error code given in the Authorization Response
*/
error: string;
/**
* Human-readable text providing additional information, used to assist the developer in
* understanding the error that occurred, given in the Authorization Response
*/
error_description?: string;
/**
* @ignore
*/
constructor(message: string, options: {
cause: URLSearchParams;
});
}
/**
* Thrown when a server responds with a parseable WWW-Authenticate challenges, typically because of
* expired tokens, or bad client authentication
*
* @example
*
* ```http
* HTTP/1.1 401 Unauthorized
* WWW-Authenticate: Bearer error="invalid_token", error_description="The access token expired"
* ```
*
* @group Errors
*/
export declare class WWWAuthenticateChallengeError extends Error {
/**
* The parsed WWW-Authenticate HTTP Header challenges
*/
cause: WWWAuthenticateChallenge[];
code: typeof WWW_AUTHENTICATE_CHALLENGE;
/**
* The {@link !Response} that included a WWW-Authenticate HTTP Header challenges, its
* {@link !Response.bodyUsed} is `false`
*/
response: Response;
/**
* HTTP Status Code of the response
*/
status: number;
/**
* @ignore
*/
constructor(message: string, options: {
cause: WWWAuthenticateChallenge[];
response: Response;
});
}
/**
* WWW-Authenticate challenge auth-param dictionary with known and unknown parameter names
*/
export interface WWWAuthenticateChallengeParameters {
/**
* Identifies the protection space
*/
readonly realm?: string;
/**
* A machine-readable error code value
*/
readonly error?: string;
/**
* Human-readable ASCII text providing additional information, used to assist the client developer
* in understanding the error that occurred
*/
readonly error_description?: string;
/**