oauth4webapi 2.8.1 → 2.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -44,7 +44,7 @@ import * as oauth2 from 'oauth4webapi'
44
44
  **`example`** Deno import
45
45
 
46
46
  ```js
47
- import * as oauth2 from 'https://deno.land/x/oauth4webapi@v2.8.1/mod.ts'
47
+ import * as oauth2 from 'https://deno.land/x/oauth4webapi@v2.10.0/mod.ts'
48
48
  ```
49
49
 
50
50
  - Authorization Code Flow - OpenID Connect [source](examples/code.ts), or plain OAuth 2 [source](examples/oauth.ts)
package/build/index.d.ts CHANGED
@@ -1,12 +1,20 @@
1
- /** JSON Object */
1
+ /**
2
+ * JSON Object
3
+ */
2
4
  export type JsonObject = {
3
5
  [Key in string]?: JsonValue;
4
6
  };
5
- /** JSON Array */
7
+ /**
8
+ * JSON Array
9
+ */
6
10
  export type JsonArray = JsonValue[];
7
- /** JSON Primitives */
11
+ /**
12
+ * JSON Primitives
13
+ */
8
14
  export type JsonPrimitive = string | number | boolean | null;
9
- /** JSON Values */
15
+ /**
16
+ * JSON Values
17
+ */
10
18
  export type JsonValue = JsonPrimitive | JsonObject | JsonArray;
11
19
  /**
12
20
  * Interface to pass an asymmetric private key and, optionally, its associated JWK Key ID to be
@@ -130,9 +138,6 @@ export type JWSAlgorithm = 'PS256' | 'ES256' | 'RS256' | 'EdDSA' | 'ES384' | 'PS
130
138
  export declare const clockSkew: unique symbol;
131
139
  export declare const clockTolerance: unique symbol;
132
140
  /**
133
- * This is an experimental feature, it is not subject to semantic versioning rules. Non-backward
134
- * compatible changes or removal may occur in any future release.
135
- *
136
141
  * When configured on an interface that extends {@link HttpRequestOptions}, that's every `options`
137
142
  * parameter for functions that trigger HTTP Requests, this replaces the use of global fetch. As a
138
143
  * fetch replacement the arguments and expected return are the same as fetch.
@@ -156,12 +161,13 @@ export declare const clockTolerance: unique symbol;
156
161
  *
157
162
  * - Expect Type-related issues when passing the inputs through to fetch-like modules, they hardly
158
163
  * ever get their typings inline with actual fetch, you should `@ts-expect-error` them.
159
- * - Returning self-constructed {@link Response} instances prohibits AS-signalled DPoP Nonce caching.
164
+ * - Returning self-constructed {@link Response} instances prohibits AS/RS-signalled DPoP Nonce
165
+ * caching.
160
166
  *
161
167
  * @example
162
168
  *
163
- * Using [sindresorhus/ky](https://github.com/sindresorhus/ky) hooks feature for logging outgoing
164
- * requests and their responses.
169
+ * Using [sindresorhus/ky](https://github.com/sindresorhus/ky) for retries and its hooks feature for
170
+ * logging outgoing requests and their responses.
165
171
  *
166
172
  * ```js
167
173
  * import ky from 'ky'
@@ -169,7 +175,7 @@ export declare const clockTolerance: unique symbol;
169
175
  *
170
176
  * // example use
171
177
  * await oauth.discoveryRequest(new URL('https://as.example.com'), {
172
- * [oauth.experimental_customFetch]: (...args) =>
178
+ * [oauth.customFetch]: (...args) =>
173
179
  * ky(args[0], {
174
180
  * ...args[1],
175
181
  * hooks: {
@@ -195,7 +201,7 @@ export declare const clockTolerance: unique symbol;
195
201
  *
196
202
  * @example
197
203
  *
198
- * Using [nodejs/undici](https://github.com/nodejs/undici) for mocking.
204
+ * Using [nodejs/undici](https://github.com/nodejs/undici) to mock responses in tests.
199
205
  *
200
206
  * ```js
201
207
  * import * as undici from 'undici'
@@ -210,26 +216,19 @@ export declare const clockTolerance: unique symbol;
210
216
  *
211
217
  * // example use
212
218
  * await oauth.discoveryRequest(new URL('https://as.example.com'), {
213
- * [oauth.experimental_customFetch]: undici.fetch,
219
+ * [oauth.customFetch]: undici.fetch,
214
220
  * })
215
221
  * ```
216
- *
217
- * @group Experimental
218
222
  */
219
- export declare const experimental_customFetch: unique symbol;
220
- /** @ignore */
221
- export declare const experimentalCustomFetch: symbol;
223
+ export declare const customFetch: unique symbol;
222
224
  /**
223
- * This is an experimental feature, it is not subject to semantic versioning rules. Non-backward
224
- * compatible changes or removal may occur in any future release.
225
- *
226
- * When combined with {@link experimental_customFetch} (to use a Fetch API implementation that
227
- * supports client certificates) this can be used to target FAPI 2.0 profiles that utilize
228
- * Mutual-TLS for either client authentication or sender constraining. FAPI 1.0 Advanced profiles
229
- * that use PAR and JARM can also be targetted.
225
+ * When combined with {@link customFetch} (to use a Fetch API implementation that supports client
226
+ * certificates) this can be used to target FAPI 2.0 profiles that utilize Mutual-TLS for either
227
+ * client authentication or sender constraining. FAPI 1.0 Advanced profiles that use PAR and JARM
228
+ * can also be targetted.
230
229
  *
231
- * When configured on an interface that extends {@link ExperimentalUseMTLSAliasOptions} this makes
232
- * the client prioritize an endpoint URL present in
230
+ * When configured on an interface that extends {@link UseMTLSAliasOptions} this makes the client
231
+ * prioritize an endpoint URL present in
233
232
  * {@link AuthorizationServer.mtls_endpoint_aliases `as.mtls_endpoint_aliases`}.
234
233
  *
235
234
  * @example
@@ -242,8 +241,8 @@ export declare const experimentalCustomFetch: symbol;
242
241
  * import * as oauth from 'oauth4webapi'
243
242
  *
244
243
  * const response = await oauth.pushedAuthorizationRequest(as, client, params, {
245
- * [oauth.experimental_useMtlsAlias]: true,
246
- * [oauth.experimental_customFetch]: (...args) => {
244
+ * [oauth.useMtlsAlias]: true,
245
+ * [oauth.customFetch]: (...args) => {
247
246
  * return undici.fetch(args[0], {
248
247
  * ...args[1],
249
248
  * dispatcher: new undici.Agent({
@@ -272,8 +271,8 @@ export declare const experimentalCustomFetch: symbol;
272
271
  * })
273
272
  *
274
273
  * const response = await oauth.pushedAuthorizationRequest(as, client, params, {
275
- * [oauth.experimental_useMtlsAlias]: true,
276
- * [oauth.experimental_customFetch]: (...args) => {
274
+ * [oauth.useMtlsAlias]: true,
275
+ * [oauth.customFetch]: (...args) => {
277
276
  * return fetch(args[0], {
278
277
  * ...args[1],
279
278
  * client: agent,
@@ -282,30 +281,38 @@ export declare const experimentalCustomFetch: symbol;
282
281
  * })
283
282
  * ```
284
283
  *
285
- * @group Experimental
286
- *
287
284
  * @see [RFC 8705 - OAuth 2.0 Mutual-TLS Client Authentication and Certificate-Bound Access Tokens](https://www.rfc-editor.org/rfc/rfc8705.html)
288
285
  */
289
- export declare const experimental_useMtlsAlias: unique symbol;
290
- /** @ignore */
291
- export declare const experimentalUseMtlsAlias: symbol;
286
+ export declare const useMtlsAlias: unique symbol;
292
287
  /**
293
288
  * Authorization Server Metadata
294
289
  *
295
290
  * @see [IANA OAuth Authorization Server Metadata registry](https://www.iana.org/assignments/oauth-parameters/oauth-parameters.xhtml#authorization-server-metadata)
296
291
  */
297
292
  export interface AuthorizationServer {
298
- /** Authorization server's Issuer Identifier URL. */
293
+ /**
294
+ * Authorization server's Issuer Identifier URL.
295
+ */
299
296
  readonly issuer: string;
300
- /** URL of the authorization server's authorization endpoint. */
297
+ /**
298
+ * URL of the authorization server's authorization endpoint.
299
+ */
301
300
  readonly authorization_endpoint?: string;
302
- /** URL of the authorization server's token endpoint. */
301
+ /**
302
+ * URL of the authorization server's token endpoint.
303
+ */
303
304
  readonly token_endpoint?: string;
304
- /** URL of the authorization server's JWK Set document. */
305
+ /**
306
+ * URL of the authorization server's JWK Set document.
307
+ */
305
308
  readonly jwks_uri?: string;
306
- /** URL of the authorization server's Dynamic Client Registration Endpoint. */
309
+ /**
310
+ * URL of the authorization server's Dynamic Client Registration Endpoint.
311
+ */
307
312
  readonly registration_endpoint?: string;
308
- /** JSON array containing a list of the `scope` values that this authorization server supports. */
313
+ /**
314
+ * JSON array containing a list of the `scope` values that this authorization server supports.
315
+ */
309
316
  readonly scopes_supported?: string[];
310
317
  /**
311
318
  * JSON array containing a list of the `response_type` values that this authorization server
@@ -322,7 +329,9 @@ export interface AuthorizationServer {
322
329
  * supports.
323
330
  */
324
331
  readonly grant_types_supported?: string[];
325
- /** JSON array containing a list of client authentication methods supported by this token endpoint. */
332
+ /**
333
+ * JSON array containing a list of client authentication methods supported by this token endpoint.
334
+ */
326
335
  readonly token_endpoint_auth_methods_supported?: string[];
327
336
  /**
328
337
  * JSON array containing a list of the JWS signing algorithms supported by the token endpoint for
@@ -350,7 +359,9 @@ export interface AuthorizationServer {
350
359
  * the authorization server's terms of service.
351
360
  */
352
361
  readonly op_tos_uri?: string;
353
- /** URL of the authorization server's revocation endpoint. */
362
+ /**
363
+ * URL of the authorization server's revocation endpoint.
364
+ */
354
365
  readonly revocation_endpoint?: string;
355
366
  /**
356
367
  * JSON array containing a list of client authentication methods supported by this revocation
@@ -362,7 +373,9 @@ export interface AuthorizationServer {
362
373
  * for the signature on the JWT used to authenticate the client at the revocation endpoint.
363
374
  */
364
375
  readonly revocation_endpoint_auth_signing_alg_values_supported?: string[];
365
- /** URL of the authorization server's introspection endpoint. */
376
+ /**
377
+ * URL of the authorization server's introspection endpoint.
378
+ */
366
379
  readonly introspection_endpoint?: string;
367
380
  /**
368
381
  * JSON array containing a list of client authentication methods supported by this introspection
@@ -375,20 +388,30 @@ export interface AuthorizationServer {
375
388
  * endpoint.
376
389
  */
377
390
  readonly introspection_endpoint_auth_signing_alg_values_supported?: string[];
378
- /** PKCE code challenge methods supported by this authorization server. */
391
+ /**
392
+ * PKCE code challenge methods supported by this authorization server.
393
+ */
379
394
  readonly code_challenge_methods_supported?: string[];
380
- /** Signed JWT containing metadata values about the authorization server as claims. */
395
+ /**
396
+ * Signed JWT containing metadata values about the authorization server as claims.
397
+ */
381
398
  readonly signed_metadata?: string;
382
- /** URL of the authorization server's device authorization endpoint. */
399
+ /**
400
+ * URL of the authorization server's device authorization endpoint.
401
+ */
383
402
  readonly device_authorization_endpoint?: string;
384
- /** Indicates authorization server support for mutual-TLS client certificate-bound access tokens. */
403
+ /**
404
+ * Indicates authorization server support for mutual-TLS client certificate-bound access tokens.
405
+ */
385
406
  readonly tls_client_certificate_bound_access_tokens?: boolean;
386
407
  /**
387
408
  * JSON object containing alternative authorization server endpoints, which a client intending to
388
409
  * do mutual TLS will use in preference to the conventional endpoints.
389
410
  */
390
411
  readonly mtls_endpoint_aliases?: MTLSEndpointAliases;
391
- /** URL of the authorization server's UserInfo Endpoint. */
412
+ /**
413
+ * URL of the authorization server's UserInfo Endpoint.
414
+ */
392
415
  readonly userinfo_endpoint?: string;
393
416
  /**
394
417
  * JSON array containing a list of the Authentication Context Class References that this
@@ -415,11 +438,17 @@ export interface AuthorizationServer {
415
438
  * the ID Token.
416
439
  */
417
440
  readonly id_token_encryption_enc_values_supported?: string[];
418
- /** JSON array containing a list of the JWS `alg` values supported by the UserInfo Endpoint. */
441
+ /**
442
+ * JSON array containing a list of the JWS `alg` values supported by the UserInfo Endpoint.
443
+ */
419
444
  readonly userinfo_signing_alg_values_supported?: string[];
420
- /** JSON array containing a list of the JWE `alg` values supported by the UserInfo Endpoint. */
445
+ /**
446
+ * JSON array containing a list of the JWE `alg` values supported by the UserInfo Endpoint.
447
+ */
421
448
  readonly userinfo_encryption_alg_values_supported?: string[];
422
- /** JSON array containing a list of the JWE `enc` values supported by the UserInfo Endpoint. */
449
+ /**
450
+ * JSON array containing a list of the JWE `enc` values supported by the UserInfo Endpoint.
451
+ */
423
452
  readonly userinfo_encryption_enc_values_supported?: string[];
424
453
  /**
425
454
  * JSON array containing a list of the JWS `alg` values supported by the authorization server for
@@ -441,7 +470,9 @@ export interface AuthorizationServer {
441
470
  * supports.
442
471
  */
443
472
  readonly display_values_supported?: string[];
444
- /** JSON array containing a list of the Claim Types that the authorization server supports. */
473
+ /**
474
+ * JSON array containing a list of the Claim Types that the authorization server supports.
475
+ */
445
476
  readonly claim_types_supported?: string[];
446
477
  /**
447
478
  * JSON array containing a list of the Claim Names of the Claims that the authorization server MAY
@@ -478,9 +509,13 @@ export interface AuthorizationServer {
478
509
  * through either `request` or `request_uri` parameter.
479
510
  */
480
511
  readonly require_signed_request_object?: boolean;
481
- /** URL of the authorization server's pushed authorization request endpoint. */
512
+ /**
513
+ * URL of the authorization server's pushed authorization request endpoint.
514
+ */
482
515
  readonly pushed_authorization_request_endpoint?: string;
483
- /** Indicates whether the authorization server accepts authorization requests only via PAR. */
516
+ /**
517
+ * Indicates whether the authorization server accepts authorization requests only via PAR.
518
+ */
484
519
  readonly require_pushed_authorization_requests?: boolean;
485
520
  /**
486
521
  * JSON array containing a list of algorithms supported by the authorization server for
@@ -517,23 +552,31 @@ export interface AuthorizationServer {
517
552
  * introspection response encryption (`enc` value).
518
553
  */
519
554
  readonly authorization_encryption_enc_values_supported?: string[];
520
- /** CIBA Backchannel Authentication Endpoint. */
555
+ /**
556
+ * CIBA Backchannel Authentication Endpoint.
557
+ */
521
558
  readonly backchannel_authentication_endpoint?: string;
522
559
  /**
523
560
  * JSON array containing a list of the JWS signing algorithms supported for validation of signed
524
561
  * CIBA authentication requests.
525
562
  */
526
563
  readonly backchannel_authentication_request_signing_alg_values_supported?: string[];
527
- /** Supported CIBA authentication result delivery modes. */
564
+ /**
565
+ * Supported CIBA authentication result delivery modes.
566
+ */
528
567
  readonly backchannel_token_delivery_modes_supported?: string[];
529
- /** Indicates whether the authorization server supports the use of the CIBA `user_code` parameter. */
568
+ /**
569
+ * Indicates whether the authorization server supports the use of the CIBA `user_code` parameter.
570
+ */
530
571
  readonly backchannel_user_code_parameter_supported?: boolean;
531
572
  /**
532
573
  * URL of an authorization server iframe that supports cross-origin communications for session
533
574
  * state information with the RP Client, using the HTML5 postMessage API.
534
575
  */
535
576
  readonly check_session_iframe?: string;
536
- /** JSON array containing a list of the JWS algorithms supported for DPoP proof JWTs. */
577
+ /**
578
+ * JSON array containing a list of the JWS algorithms supported for DPoP proof JWTs.
579
+ */
537
580
  readonly dpop_signing_alg_values_supported?: string[];
538
581
  /**
539
582
  * URL at the authorization server to which an RP can perform a redirect to request that the
@@ -546,14 +589,18 @@ export interface AuthorizationServer {
546
589
  * `frontchannel_logout_uri` is used.
547
590
  */
548
591
  readonly frontchannel_logout_session_supported?: boolean;
549
- /** Boolean value specifying whether the authorization server supports HTTP-based logout. */
592
+ /**
593
+ * Boolean value specifying whether the authorization server supports HTTP-based logout.
594
+ */
550
595
  readonly frontchannel_logout_supported?: boolean;
551
596
  /**
552
597
  * Boolean value specifying whether the authorization server can pass a `sid` (session ID) Claim
553
598
  * in the Logout Token to identify the RP session with the OP.
554
599
  */
555
600
  readonly backchannel_logout_session_supported?: boolean;
556
- /** Boolean value specifying whether the authorization server supports back-channel logout. */
601
+ /**
602
+ * Boolean value specifying whether the authorization server supports back-channel logout.
603
+ */
557
604
  readonly backchannel_logout_supported?: boolean;
558
605
  readonly [metadata: string]: JsonValue | undefined;
559
606
  }
@@ -566,9 +613,13 @@ export interface MTLSEndpointAliases extends Pick<AuthorizationServer, 'token_en
566
613
  * @see [IANA OAuth Client Registration Metadata registry](https://www.iana.org/assignments/oauth-parameters/oauth-parameters.xhtml#client-metadata)
567
614
  */
568
615
  export interface Client {
569
- /** Client identifier. */
616
+ /**
617
+ * Client identifier.
618
+ */
570
619
  client_id: string;
571
- /** Client secret. */
620
+ /**
621
+ * Client secret.
622
+ */
572
623
  client_secret?: string;
573
624
  /**
574
625
  * Client {@link ClientAuthenticationMethod authentication method} for the client's authenticated
@@ -608,7 +659,9 @@ export interface Client {
608
659
  * and fall back to `RS256` when the authorization server metadata is not set.
609
660
  */
610
661
  introspection_signed_response_alg?: string;
611
- /** Default Maximum Authentication Age. */
662
+ /**
663
+ * Default Maximum Authentication Age.
664
+ */
612
665
  default_max_age?: number;
613
666
  /**
614
667
  * Use to adjust the client's assumed current time. Positive and negative finite values
@@ -658,11 +711,15 @@ export interface Client {
658
711
  [clockTolerance]?: number;
659
712
  [metadata: string]: JsonValue | undefined;
660
713
  }
661
- /** @group Errors */
714
+ /**
715
+ * @group Errors
716
+ */
662
717
  export declare class UnsupportedOperationError extends Error {
663
718
  constructor(message?: string);
664
719
  }
665
- /** @group Errors */
720
+ /**
721
+ * @group Errors
722
+ */
666
723
  export declare class OperationProcessingError extends Error {
667
724
  constructor(message: string, options?: {
668
725
  cause?: unknown;
@@ -682,20 +739,19 @@ export interface HttpRequestOptions {
682
739
  * ```
683
740
  */
684
741
  signal?: (() => AbortSignal) | AbortSignal;
685
- /** Headers to additionally send with the HTTP Request(s) triggered by this function's invocation. */
742
+ /**
743
+ * Headers to additionally send with the HTTP Request(s) triggered by this function's invocation.
744
+ */
686
745
  headers?: [string, string][] | Record<string, string> | Headers;
687
746
  /**
688
- * This is an experimental feature, it is not subject to semantic versioning rules. Non-backward
689
- * compatible changes or removal may occur in any future release.
690
- *
691
- * See {@link experimental_customFetch} for its documentation.
692
- *
693
- * @group Experimental
747
+ * See {@link customFetch}.
694
748
  */
695
- [experimental_customFetch]?: typeof fetch;
749
+ [customFetch]?: typeof fetch;
696
750
  }
697
751
  export interface DiscoveryRequestOptions extends HttpRequestOptions {
698
- /** The issuer transformation algorithm to use. */
752
+ /**
753
+ * The issuer transformation algorithm to use.
754
+ */
699
755
  algorithm?: 'oidc' | 'oauth2';
700
756
  }
701
757
  /**
@@ -737,9 +793,9 @@ export declare function processDiscoveryResponse(expectedIssuerIdentifier: URL,
737
793
  * @group Utilities
738
794
  * @group Authorization Code Grant
739
795
  * @group Authorization Code Grant w/ OpenID Connect (OIDC)
740
- * @group Proof Key for Code Exchange by OAuth Public Clients (PKCE)
796
+ * @group Proof Key for Code Exchange (PKCE)
741
797
  *
742
- * @see [RFC 7636 - Proof Key for Code Exchange by OAuth Public Clients (PKCE)](https://www.rfc-editor.org/rfc/rfc7636.html#section-4)
798
+ * @see [RFC 7636 - Proof Key for Code Exchange (PKCE)](https://www.rfc-editor.org/rfc/rfc7636.html#section-4)
743
799
  */
744
800
  export declare function generateRandomCodeVerifier(): string;
745
801
  /**
@@ -766,9 +822,9 @@ export declare function generateRandomNonce(): string;
766
822
  *
767
823
  * @group Authorization Code Grant
768
824
  * @group Authorization Code Grant w/ OpenID Connect (OIDC)
769
- * @group Proof Key for Code Exchange by OAuth Public Clients (PKCE)
825
+ * @group Proof Key for Code Exchange (PKCE)
770
826
  *
771
- * @see [RFC 7636 - Proof Key for Code Exchange by OAuth Public Clients (PKCE)](https://www.rfc-editor.org/rfc/rfc7636.html#section-4)
827
+ * @see [RFC 7636 - Proof Key for Code Exchange (PKCE)](https://www.rfc-editor.org/rfc/rfc7636.html#section-4)
772
828
  */
773
829
  export declare function calculatePKCECodeChallenge(codeVerifier: string): Promise<string>;
774
830
  export interface DPoPOptions extends CryptoKeyPair {
@@ -778,7 +834,9 @@ export interface DPoPOptions extends CryptoKeyPair {
778
834
  * Its algorithm must be compatible with a supported {@link JWSAlgorithm JWS `alg` Algorithm}.
779
835
  */
780
836
  privateKey: CryptoKey;
781
- /** The public key corresponding to {@link DPoPOptions.privateKey}. */
837
+ /**
838
+ * The public key corresponding to {@link DPoPOptions.privateKey}.
839
+ */
782
840
  publicKey: CryptoKey;
783
841
  /**
784
842
  * Server-Provided Nonce to use in the request. This option serves as an override in case the
@@ -788,21 +846,18 @@ export interface DPoPOptions extends CryptoKeyPair {
788
846
  nonce?: string;
789
847
  }
790
848
  export interface DPoPRequestOptions {
791
- /** DPoP-related options. */
849
+ /**
850
+ * DPoP-related options.
851
+ */
792
852
  DPoP?: DPoPOptions;
793
853
  }
794
- export interface ExperimentalUseMTLSAliasOptions {
854
+ export interface UseMTLSAliasOptions {
795
855
  /**
796
- * This is an experimental feature, it is not subject to semantic versioning rules. Non-backward
797
- * compatible changes or removal may occur in any future release.
798
- *
799
- * See {@link experimental_useMtlsAlias} for its documentation.
800
- *
801
- * @group Experimental
856
+ * See {@link useMtlsAlias}.
802
857
  */
803
- [experimental_useMtlsAlias]?: boolean;
858
+ [useMtlsAlias]?: boolean;
804
859
  }
805
- export interface AuthenticatedRequestOptions extends ExperimentalUseMTLSAliasOptions {
860
+ export interface AuthenticatedRequestOptions extends UseMTLSAliasOptions {
806
861
  /**
807
862
  * Private key to use for `private_key_jwt`
808
863
  * {@link ClientAuthenticationMethod client authentication}. Its algorithm must be compatible with
@@ -874,11 +929,15 @@ export interface WWWAuthenticateChallengeParameters {
874
929
  readonly error_uri?: string;
875
930
  readonly algs?: string;
876
931
  readonly scope?: string;
877
- /** NOTE: because the parameter names are case insensitive they are always returned lowercased */
932
+ /**
933
+ * NOTE: because the parameter names are case insensitive they are always returned lowercased
934
+ */
878
935
  readonly [parameter: Lowercase<string>]: string | undefined;
879
936
  }
880
937
  export interface WWWAuthenticateChallenge {
881
- /** NOTE: because the value is case insensitive it is always returned lowercased */
938
+ /**
939
+ * NOTE: because the value is case insensitive it is always returned lowercased
940
+ */
882
941
  readonly scheme: Lowercase<string>;
883
942
  readonly parameters: WWWAuthenticateChallengeParameters;
884
943
  }
@@ -944,7 +1003,7 @@ export interface ProtectedResourceRequestOptions extends Omit<HttpRequestOptions
944
1003
  * @see [RFC 9449 - OAuth 2.0 Demonstrating Proof-of-Possession at the Application Layer (DPoP)](https://www.rfc-editor.org/rfc/rfc9449.html#name-protected-resource-access)
945
1004
  */
946
1005
  export declare function protectedResourceRequest(accessToken: string, method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | string, url: URL, headers: Headers, body?: ReadableStream | Blob | ArrayBufferView | ArrayBuffer | FormData | URLSearchParams | string | null, options?: ProtectedResourceRequestOptions): Promise<Response>;
947
- export interface UserInfoRequestOptions extends HttpRequestOptions, DPoPRequestOptions, ExperimentalUseMTLSAliasOptions {
1006
+ export interface UserInfoRequestOptions extends HttpRequestOptions, DPoPRequestOptions, UseMTLSAliasOptions {
948
1007
  }
949
1008
  /**
950
1009
  * Performs a UserInfo Request at the
@@ -1025,7 +1084,9 @@ export declare const skipSubjectCheck: unique symbol;
1025
1084
  */
1026
1085
  export declare function processUserInfoResponse(as: AuthorizationServer, client: Client, expectedSubject: string | typeof skipSubjectCheck, response: Response): Promise<UserInfoResponse>;
1027
1086
  export interface TokenEndpointRequestOptions extends HttpRequestOptions, AuthenticatedRequestOptions, DPoPRequestOptions {
1028
- /** Any additional parameters to send. This cannot override existing parameter values. */
1087
+ /**
1088
+ * Any additional parameters to send. This cannot override existing parameter values.
1089
+ */
1029
1090
  additionalParameters?: URLSearchParams | Record<string, string> | string[][];
1030
1091
  }
1031
1092
  /**
@@ -1097,7 +1158,7 @@ export declare function processRefreshTokenResponse(as: AuthorizationServer, cli
1097
1158
  *
1098
1159
  * @see [RFC 6749 - The OAuth 2.0 Authorization Framework](https://www.rfc-editor.org/rfc/rfc6749.html#section-4.1)
1099
1160
  * @see [OpenID Connect Core 1.0](https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth)
1100
- * @see [RFC 7636 - Proof Key for Code Exchange by OAuth Public Clients (PKCE)](https://www.rfc-editor.org/rfc/rfc7636.html#section-4)
1161
+ * @see [RFC 7636 - Proof Key for Code Exchange (PKCE)](https://www.rfc-editor.org/rfc/rfc7636.html#section-4)
1101
1162
  * @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-access-token-request)
1102
1163
  */
1103
1164
  export declare function authorizationCodeGrantRequest(as: AuthorizationServer, client: Client, callbackParameters: URLSearchParams, redirectUri: string, codeVerifier: string, options?: TokenEndpointRequestOptions): Promise<Response>;
@@ -1123,13 +1184,25 @@ export interface IDToken extends JWTPayload {
1123
1184
  readonly azp?: string;
1124
1185
  readonly [claim: string]: JsonValue | undefined;
1125
1186
  }
1187
+ export interface AuthorizationDetails {
1188
+ readonly type: string;
1189
+ readonly locations?: string[];
1190
+ readonly actions?: string[];
1191
+ readonly datatypes?: string[];
1192
+ readonly privileges?: string[];
1193
+ readonly identifier?: string;
1194
+ readonly [parameter: string]: JsonValue | undefined;
1195
+ }
1126
1196
  export interface TokenEndpointResponse {
1127
1197
  readonly access_token: string;
1128
1198
  readonly expires_in?: number;
1129
1199
  readonly id_token?: string;
1130
1200
  readonly refresh_token?: string;
1131
1201
  readonly scope?: string;
1132
- /** NOTE: because the value is case insensitive it is always returned lowercased */
1202
+ readonly authorization_details?: AuthorizationDetails[];
1203
+ /**
1204
+ * NOTE: because the value is case insensitive it is always returned lowercased
1205
+ */
1133
1206
  readonly token_type: 'bearer' | 'dpop' | Lowercase<string>;
1134
1207
  readonly [parameter: string]: JsonValue | undefined;
1135
1208
  }
@@ -1139,7 +1212,10 @@ export interface OpenIDTokenEndpointResponse {
1139
1212
  readonly id_token: string;
1140
1213
  readonly refresh_token?: string;
1141
1214
  readonly scope?: string;
1142
- /** NOTE: because the value is case insensitive it is always returned lowercased */
1215
+ readonly authorization_details?: AuthorizationDetails[];
1216
+ /**
1217
+ * NOTE: because the value is case insensitive it is always returned lowercased
1218
+ */
1143
1219
  readonly token_type: 'bearer' | 'dpop' | Lowercase<string>;
1144
1220
  readonly [parameter: string]: JsonValue | undefined;
1145
1221
  }
@@ -1149,7 +1225,10 @@ export interface OAuth2TokenEndpointResponse {
1149
1225
  readonly id_token?: undefined;
1150
1226
  readonly refresh_token?: string;
1151
1227
  readonly scope?: string;
1152
- /** NOTE: because the value is case insensitive it is always returned lowercased */
1228
+ readonly authorization_details?: AuthorizationDetails[];
1229
+ /**
1230
+ * NOTE: because the value is case insensitive it is always returned lowercased
1231
+ */
1153
1232
  readonly token_type: 'bearer' | 'dpop' | Lowercase<string>;
1154
1233
  readonly [parameter: string]: JsonValue | undefined;
1155
1234
  }
@@ -1157,7 +1236,10 @@ export interface ClientCredentialsGrantResponse {
1157
1236
  readonly access_token: string;
1158
1237
  readonly expires_in?: number;
1159
1238
  readonly scope?: string;
1160
- /** NOTE: because the value is case insensitive it is always returned lowercased */
1239
+ readonly authorization_details?: AuthorizationDetails[];
1240
+ /**
1241
+ * NOTE: because the value is case insensitive it is always returned lowercased
1242
+ */
1161
1243
  readonly token_type: 'bearer' | 'dpop' | Lowercase<string>;
1162
1244
  readonly [parameter: string]: JsonValue | undefined;
1163
1245
  }
@@ -1246,7 +1328,9 @@ export declare function clientCredentialsGrantRequest(as: AuthorizationServer, c
1246
1328
  */
1247
1329
  export declare function processClientCredentialsResponse(as: AuthorizationServer, client: Client, response: Response): Promise<ClientCredentialsGrantResponse | OAuth2Error>;
1248
1330
  export interface RevocationRequestOptions extends HttpRequestOptions, AuthenticatedRequestOptions {
1249
- /** Any additional parameters to send. This cannot override existing parameter values. */
1331
+ /**
1332
+ * Any additional parameters to send. This cannot override existing parameter values.
1333
+ */
1250
1334
  additionalParameters?: URLSearchParams | Record<string, string> | string[][];
1251
1335
  }
1252
1336
  /**
@@ -1278,7 +1362,9 @@ export declare function revocationRequest(as: AuthorizationServer, client: Clien
1278
1362
  */
1279
1363
  export declare function processRevocationResponse(response: Response): Promise<undefined | OAuth2Error>;
1280
1364
  export interface IntrospectionRequestOptions extends HttpRequestOptions, AuthenticatedRequestOptions {
1281
- /** Any additional parameters to send. This cannot override existing parameter values. */
1365
+ /**
1366
+ * Any additional parameters to send. This cannot override existing parameter values.
1367
+ */
1282
1368
  additionalParameters?: URLSearchParams | Record<string, string> | string[][];
1283
1369
  /**
1284
1370
  * Request a JWT Response from the
@@ -1311,8 +1397,6 @@ export interface ConfirmationClaims {
1311
1397
  readonly jkt?: string;
1312
1398
  readonly [claim: string]: JsonValue | undefined;
1313
1399
  }
1314
- /** @ignore */
1315
- export type IntrospectionConfirmationClaims = ConfirmationClaims;
1316
1400
  export interface IntrospectionResponse {
1317
1401
  readonly active: boolean;
1318
1402
  readonly client_id?: string;
@@ -1323,11 +1407,12 @@ export interface IntrospectionResponse {
1323
1407
  readonly jti?: string;
1324
1408
  readonly username?: string;
1325
1409
  readonly aud?: string | string[];
1326
- readonly scope: string;
1410
+ readonly scope?: string;
1327
1411
  readonly sub?: string;
1328
1412
  readonly nbf?: number;
1329
1413
  readonly token_type?: string;
1330
1414
  readonly cnf?: ConfirmationClaims;
1415
+ readonly authorization_details?: AuthorizationDetails[];
1331
1416
  readonly [claim: string]: JsonValue | undefined;
1332
1417
  }
1333
1418
  /**
@@ -1366,9 +1451,6 @@ export declare function processIntrospectionResponse(as: AuthorizationServer, cl
1366
1451
  */
1367
1452
  export declare function validateJwtAuthResponse(as: AuthorizationServer, client: Client, parameters: URLSearchParams | URL, expectedState?: string | typeof expectNoState | typeof skipStateCheck, options?: HttpRequestOptions): Promise<URLSearchParams | OAuth2Error>;
1368
1453
  /**
1369
- * This is an experimental feature, it is not subject to semantic versioning rules. Non-backward
1370
- * compatible changes or removal may occur in any future release.
1371
- *
1372
1454
  * Same as {@link validateAuthResponse} but for FAPI 1.0 Advanced Detached Signature authorization
1373
1455
  * responses.
1374
1456
  *
@@ -1387,11 +1469,10 @@ export declare function validateJwtAuthResponse(as: AuthorizationServer, client:
1387
1469
  * @returns Validated Authorization Response parameters or Authorization Error Response.
1388
1470
  *
1389
1471
  * @group FAPI 1.0 Advanced
1390
- * @group Experimental
1391
1472
  *
1392
1473
  * @see [Financial-grade API Security Profile 1.0 - Part 2: Advanced](https://openid.net/specs/openid-financial-api-part-2-1_0.html#id-token-as-detached-signature)
1393
1474
  */
1394
- export declare function experimental_validateDetachedSignatureResponse(as: AuthorizationServer, client: Client, parameters: URLSearchParams | URL, expectedNonce: string, expectedState?: string | typeof expectNoState, maxAge?: number | typeof skipAuthTimeCheck, options?: HttpRequestOptions): Promise<URLSearchParams | OAuth2Error>;
1475
+ export declare function validateDetachedSignatureResponse(as: AuthorizationServer, client: Client, parameters: URLSearchParams | URL, expectedNonce: string, expectedState?: string | typeof expectNoState, maxAge?: number | typeof skipAuthTimeCheck, options?: HttpRequestOptions): Promise<URLSearchParams | OAuth2Error>;
1395
1476
  /**
1396
1477
  * DANGER ZONE
1397
1478
  *
@@ -1501,11 +1582,17 @@ export declare function deviceCodeGrantRequest(as: AuthorizationServer, client:
1501
1582
  */
1502
1583
  export declare function processDeviceCodeResponse(as: AuthorizationServer, client: Client, response: Response): Promise<TokenEndpointResponse | OAuth2Error>;
1503
1584
  export interface GenerateKeyPairOptions {
1504
- /** Indicates whether or not the private key may be exported. Default is `false`. */
1585
+ /**
1586
+ * Indicates whether or not the private key may be exported. Default is `false`.
1587
+ */
1505
1588
  extractable?: boolean;
1506
- /** (RSA algorithms only) The length, in bits, of the RSA modulus. Default is `2048`. */
1589
+ /**
1590
+ * (RSA algorithms only) The length, in bits, of the RSA modulus. Default is `2048`.
1591
+ */
1507
1592
  modulusLength?: number;
1508
- /** (EdDSA algorithms only) The EdDSA sub-type. Default is `Ed25519`. */
1593
+ /**
1594
+ * (EdDSA algorithms only) The EdDSA sub-type. Default is `Ed25519`.
1595
+ */
1509
1596
  crv?: 'Ed25519' | 'Ed448';
1510
1597
  }
1511
1598
  /**
@@ -1524,20 +1611,25 @@ export interface JWTAccessTokenClaims extends JWTPayload {
1524
1611
  readonly iat: number;
1525
1612
  readonly jti: string;
1526
1613
  readonly client_id: string;
1614
+ readonly authorization_details?: AuthorizationDetails[];
1615
+ readonly scope?: string;
1527
1616
  readonly [claim: string]: JsonValue | undefined;
1528
1617
  }
1529
1618
  export interface ValidateJWTAccessTokenOptions extends HttpRequestOptions {
1530
- /** Indicates whether DPoP use is required. */
1619
+ /**
1620
+ * Indicates whether DPoP use is required.
1621
+ */
1531
1622
  requireDPoP?: boolean;
1532
- /** Same functionality as in {@link Client} */
1623
+ /**
1624
+ * Same functionality as in {@link Client}
1625
+ */
1533
1626
  [clockSkew]?: number;
1534
- /** Same functionality as in {@link Client} */
1627
+ /**
1628
+ * Same functionality as in {@link Client}
1629
+ */
1535
1630
  [clockTolerance]?: number;
1536
1631
  }
1537
1632
  /**
1538
- * This is an experimental feature, it is not subject to semantic versioning rules. Non-backward
1539
- * compatible changes or removal may occur in any future release.
1540
- *
1541
1633
  * Validates use of JSON Web Token (JWT) OAuth 2.0 Access Tokens for a given {@link Request} as per
1542
1634
  * RFC 9068 and optionally also RFC 9449.
1543
1635
  *
@@ -1562,10 +1654,57 @@ export interface ValidateJWTAccessTokenOptions extends HttpRequestOptions {
1562
1654
  * @param options
1563
1655
  *
1564
1656
  * @group JWT Access Tokens
1565
- * @group Experimental
1566
1657
  *
1567
1658
  * @see [RFC 9068 - JSON Web Token (JWT) Profile for OAuth 2.0 Access Tokens](https://www.rfc-editor.org/rfc/rfc9068.html)
1568
1659
  * @see [RFC 9449 - OAuth 2.0 Demonstrating Proof-of-Possession at the Application Layer (DPoP)](https://www.rfc-editor.org/rfc/rfc9449.html)
1569
1660
  */
1570
- export declare function experimental_validateJwtAccessToken(as: AuthorizationServer, request: Request, expectedAudience: string, options?: ValidateJWTAccessTokenOptions): Promise<JWTAccessTokenClaims>;
1661
+ export declare function validateJwtAccessToken(as: AuthorizationServer, request: Request, expectedAudience: string, options?: ValidateJWTAccessTokenOptions): Promise<JWTAccessTokenClaims>;
1662
+ /**
1663
+ * @ignore
1664
+ *
1665
+ * @deprecated Use {@link customFetch}.
1666
+ */
1667
+ export declare const experimentalCustomFetch: symbol;
1668
+ /**
1669
+ * @ignore
1670
+ *
1671
+ * @deprecated Use {@link customFetch}.
1672
+ */
1673
+ export declare const experimental_customFetch: symbol;
1674
+ /**
1675
+ * @ignore
1676
+ *
1677
+ * @deprecated Use {@link useMtlsAlias}.
1678
+ */
1679
+ export declare const experimentalUseMtlsAlias: symbol;
1680
+ /**
1681
+ * @ignore
1682
+ *
1683
+ * @deprecated Use {@link useMtlsAlias}.
1684
+ */
1685
+ export declare const experimental_useMtlsAlias: symbol;
1686
+ /**
1687
+ * @ignore
1688
+ *
1689
+ * @deprecated Use {@link UseMTLSAliasOptions}.
1690
+ */
1691
+ export type ExperimentalUseMTLSAliasOptions = UseMTLSAliasOptions;
1692
+ /**
1693
+ * @ignore
1694
+ *
1695
+ * @deprecated Use {@link ConfirmationClaims}.
1696
+ */
1697
+ export type IntrospectionConfirmationClaims = ConfirmationClaims;
1698
+ /**
1699
+ * @ignore
1700
+ *
1701
+ * @deprecated Use {@link validateDetachedSignatureResponse}.
1702
+ */
1703
+ export declare const experimental_validateDetachedSignatureResponse: typeof validateDetachedSignatureResponse;
1704
+ /**
1705
+ * @ignore
1706
+ *
1707
+ * @deprecated Use {@link validateJwtAccessToken}.
1708
+ */
1709
+ export declare const experimental_validateJwtAccessToken: typeof validateJwtAccessToken;
1571
1710
  export {};
package/build/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  let USER_AGENT;
2
2
  if (typeof navigator === 'undefined' || !navigator.userAgent?.startsWith?.('Mozilla/5.0 ')) {
3
3
  const NAME = 'oauth4webapi';
4
- const VERSION = 'v2.8.1';
4
+ const VERSION = 'v2.10.0';
5
5
  USER_AGENT = `${NAME}/${VERSION}`;
6
6
  }
7
7
  function looseInstanceOf(input, expected) {
@@ -18,10 +18,8 @@ function looseInstanceOf(input, expected) {
18
18
  }
19
19
  export const clockSkew = Symbol();
20
20
  export const clockTolerance = Symbol();
21
- export const experimental_customFetch = Symbol();
22
- export const experimentalCustomFetch = experimental_customFetch;
23
- export const experimental_useMtlsAlias = Symbol();
24
- export const experimentalUseMtlsAlias = experimental_useMtlsAlias;
21
+ export const customFetch = Symbol();
22
+ export const useMtlsAlias = Symbol();
25
23
  const encoder = new TextEncoder();
26
24
  const decoder = new TextDecoder();
27
25
  function buf(input) {
@@ -145,14 +143,13 @@ const SUPPORTED_JWS_ALGS = [
145
143
  ];
146
144
  function processDpopNonce(response) {
147
145
  try {
148
- if (response.headers.has('dpop-nonce')) {
149
- const url = new URL(response.url);
150
- dpopNonces.set(url.origin, response.headers.get('dpop-nonce'));
146
+ const nonce = response.headers.get('dpop-nonce');
147
+ if (nonce) {
148
+ dpopNonces.set(new URL(response.url).origin, nonce);
151
149
  }
152
150
  }
153
- finally {
154
- return response;
155
- }
151
+ catch { }
152
+ return response;
156
153
  }
157
154
  function normalizeTyp(value) {
158
155
  return value.toLowerCase().replace(/^application\//, '');
@@ -203,7 +200,7 @@ export async function discoveryRequest(issuerIdentifier, options) {
203
200
  break;
204
201
  case 'oauth2':
205
202
  if (url.pathname === '/') {
206
- url.pathname = `.well-known/oauth-authorization-server`;
203
+ url.pathname = '.well-known/oauth-authorization-server';
207
204
  }
208
205
  else {
209
206
  url.pathname = `.well-known/oauth-authorization-server/${url.pathname}`.replace('//', '/');
@@ -214,7 +211,7 @@ export async function discoveryRequest(issuerIdentifier, options) {
214
211
  }
215
212
  const headers = prepareHeaders(options?.headers);
216
213
  headers.set('accept', 'application/json');
217
- return (options?.[experimental_customFetch] || fetch)(url.href, {
214
+ return (options?.[customFetch] || fetch)(url.href, {
218
215
  headers: Object.fromEntries(headers.entries()),
219
216
  method: 'GET',
220
217
  redirect: 'manual',
@@ -344,21 +341,14 @@ function keyToJws(key) {
344
341
  }
345
342
  }
346
343
  function getClockSkew(client) {
347
- if (client && clockSkew in client) {
348
- if (Number.isFinite(client[clockSkew])) {
349
- return client[clockSkew];
350
- }
351
- }
352
- return 0;
344
+ const skew = client?.[clockSkew];
345
+ return typeof skew === 'number' && Number.isFinite(skew) ? skew : 0;
353
346
  }
354
347
  function getClockTolerance(client) {
355
- if (client && clockTolerance in client) {
356
- const tolerance = client[clockTolerance];
357
- if (Number.isFinite(tolerance) && Math.sign(tolerance) !== -1) {
358
- return tolerance;
359
- }
360
- }
361
- return 30;
348
+ const tolerance = client?.[clockTolerance];
349
+ return typeof tolerance === 'number' && Number.isFinite(tolerance) && Math.sign(tolerance) !== -1
350
+ ? tolerance
351
+ : 30;
362
352
  }
363
353
  function epochTime() {
364
354
  return Math.floor(Date.now() / 1000);
@@ -491,8 +481,8 @@ export async function issueRequestObject(as, client, parameters, privateKey) {
491
481
  resource.length > 1) {
492
482
  claims.resource = resource;
493
483
  }
494
- if (parameters.has('claims')) {
495
- const value = parameters.get('claims');
484
+ let value = parameters.get('claims');
485
+ if (value) {
496
486
  if (value === '[object Object]') {
497
487
  throw new OPE('"claims" parameter must be passed as a UTF-8 encoded JSON');
498
488
  }
@@ -542,31 +532,27 @@ async function dpopProofJwt(headers, options, url, htm, clockSkew, accessToken)
542
532
  headers.set('dpop', proof);
543
533
  }
544
534
  let jwkCache;
545
- async function publicJwk(key) {
546
- jwkCache || (jwkCache = new WeakMap());
547
- if (jwkCache.has(key)) {
548
- return jwkCache.get(key);
549
- }
535
+ async function getSetPublicJwkCache(key) {
550
536
  const { kty, e, n, x, y, crv } = await crypto.subtle.exportKey('jwk', key);
551
537
  const jwk = { kty, e, n, x, y, crv };
552
538
  jwkCache.set(key, jwk);
553
539
  return jwk;
554
540
  }
541
+ async function publicJwk(key) {
542
+ jwkCache || (jwkCache = new WeakMap());
543
+ return jwkCache.get(key) || getSetPublicJwkCache(key);
544
+ }
555
545
  function validateEndpoint(value, endpoint, options) {
556
546
  if (typeof value !== 'string') {
557
- if (options?.[experimental_useMtlsAlias]) {
547
+ if (options?.[useMtlsAlias]) {
558
548
  throw new TypeError(`"as.mtls_endpoint_aliases.${endpoint}" must be a string`);
559
549
  }
560
- else {
561
- throw new TypeError(`"as.${endpoint}" must be a string`);
562
- }
550
+ throw new TypeError(`"as.${endpoint}" must be a string`);
563
551
  }
564
552
  return new URL(value);
565
553
  }
566
554
  function resolveEndpoint(as, endpoint, options) {
567
- if (options?.[experimental_useMtlsAlias] &&
568
- as.mtls_endpoint_aliases &&
569
- endpoint in as.mtls_endpoint_aliases) {
555
+ if (options?.[useMtlsAlias] && as.mtls_endpoint_aliases && endpoint in as.mtls_endpoint_aliases) {
570
556
  return validateEndpoint(as.mtls_endpoint_aliases[endpoint], endpoint, options);
571
557
  }
572
558
  return validateEndpoint(as[endpoint], endpoint);
@@ -625,10 +611,10 @@ export function parseWwwAuthenticateChallenges(response) {
625
611
  if (!looseInstanceOf(response, Response)) {
626
612
  throw new TypeError('"response" must be an instance of Response');
627
613
  }
628
- if (!response.headers.has('www-authenticate')) {
614
+ const header = response.headers.get('www-authenticate');
615
+ if (header === null) {
629
616
  return undefined;
630
617
  }
631
- const header = response.headers.get('www-authenticate');
632
618
  const result = [];
633
619
  for (const { 1: scheme, index } of header.matchAll(SCHEMES_REGEXP)) {
634
620
  result.push([scheme, index]);
@@ -696,7 +682,7 @@ export async function protectedResourceRequest(accessToken, method, url, headers
696
682
  await dpopProofJwt(headers, options.DPoP, url, 'GET', getClockSkew({ [clockSkew]: options?.[clockSkew] }), accessToken);
697
683
  headers.set('authorization', `DPoP ${accessToken}`);
698
684
  }
699
- return (options?.[experimental_customFetch] || fetch)(url.href, {
685
+ return (options?.[customFetch] || fetch)(url.href, {
700
686
  body,
701
687
  headers: Object.fromEntries(headers.entries()),
702
688
  method,
@@ -795,7 +781,7 @@ async function getPublicSigKeyFromIssuerJwksUri(as, options, header) {
795
781
  }
796
782
  throw new OPE('error when selecting a JWT verification key, no applicable keys found');
797
783
  }
798
- else if (length !== 1) {
784
+ if (length !== 1) {
799
785
  throw new OPE('error when selecting a JWT verification key, multiple applicable keys found, a "kid" JWT Header Parameter is required');
800
786
  }
801
787
  const key = await importJwk(alg, jwk);
@@ -859,7 +845,7 @@ export async function processUserInfoResponse(as, client, expectedSubject, respo
859
845
  async function authenticatedRequest(as, client, method, url, body, headers, options) {
860
846
  await clientAuthentication(as, client, body, headers, options?.clientPrivateKey);
861
847
  headers.set('content-type', 'application/x-www-form-urlencoded;charset=UTF-8');
862
- return (options?.[experimental_customFetch] || fetch)(url.href, {
848
+ return (options?.[customFetch] || fetch)(url.href, {
863
849
  body,
864
850
  headers: Object.fromEntries(headers.entries()),
865
851
  method,
@@ -1222,7 +1208,7 @@ async function jwksRequest(as, options) {
1222
1208
  const headers = prepareHeaders(options?.headers);
1223
1209
  headers.set('accept', 'application/json');
1224
1210
  headers.append('accept', 'application/jwk-set+json');
1225
- return (options?.[experimental_customFetch] || fetch)(url.href, {
1211
+ return (options?.[customFetch] || fetch)(url.href, {
1226
1212
  headers: Object.fromEntries(headers.entries()),
1227
1213
  method: 'GET',
1228
1214
  redirect: 'manual',
@@ -1472,7 +1458,7 @@ async function idTokenHashMatches(data, actual, alg, key) {
1472
1458
  const expected = await idTokenHash(alg, data, key);
1473
1459
  return actual === expected;
1474
1460
  }
1475
- export async function experimental_validateDetachedSignatureResponse(as, client, parameters, expectedNonce, expectedState, maxAge, options) {
1461
+ export async function validateDetachedSignatureResponse(as, client, parameters, expectedNonce, expectedState, maxAge, options) {
1476
1462
  assertAs(as);
1477
1463
  assertClient(client);
1478
1464
  if (parameters instanceof URL) {
@@ -1775,8 +1761,9 @@ function normalizeHtu(htu) {
1775
1761
  url.hash = '';
1776
1762
  return url.href;
1777
1763
  }
1778
- async function validateDPoP(as, request, accessTokenClaims, options) {
1779
- if (!request.headers.has('dpop')) {
1764
+ async function validateDPoP(as, request, accessToken, accessTokenClaims, options) {
1765
+ const header = request.headers.get('dpop');
1766
+ if (header === null) {
1780
1767
  throw new OPE('operation indicated DPoP use but the request has no DPoP HTTP Header');
1781
1768
  }
1782
1769
  if (request.headers.get('authorization')?.toLowerCase().startsWith('dpop ') === false) {
@@ -1786,7 +1773,7 @@ async function validateDPoP(as, request, accessTokenClaims, options) {
1786
1773
  throw new OPE('operation indicated DPoP use but the JWT Access Token has no jkt confirmation claim');
1787
1774
  }
1788
1775
  const clockSkew = getClockSkew(options);
1789
- const proof = await validateJwt(request.headers.get('dpop'), checkSigningAlgorithm.bind(undefined, undefined, as?.dpop_signing_alg_values_supported || SUPPORTED_JWS_ALGS), async ({ jwk, alg }) => {
1776
+ const proof = await validateJwt(header, checkSigningAlgorithm.bind(undefined, undefined, as?.dpop_signing_alg_values_supported || SUPPORTED_JWS_ALGS), async ({ jwk, alg }) => {
1790
1777
  if (!jwk) {
1791
1778
  throw new OPE('DPoP Proof is missing the jwk header parameter');
1792
1779
  }
@@ -1811,7 +1798,6 @@ async function validateDPoP(as, request, accessTokenClaims, options) {
1811
1798
  throw new OPE('DPoP Proof htu mismatch');
1812
1799
  }
1813
1800
  {
1814
- const accessToken = request.headers.get('authorization').split(' ')[1];
1815
1801
  const expected = b64u(await crypto.subtle.digest('SHA-256', encoder.encode(accessToken)));
1816
1802
  if (proof.claims.ath !== expected) {
1817
1803
  throw new OPE('DPoP Proof ath mismatch');
@@ -1851,7 +1837,7 @@ async function validateDPoP(as, request, accessTokenClaims, options) {
1851
1837
  }
1852
1838
  }
1853
1839
  }
1854
- export async function experimental_validateJwtAccessToken(as, request, expectedAudience, options) {
1840
+ export async function validateJwtAccessToken(as, request, expectedAudience, options) {
1855
1841
  assertAs(as);
1856
1842
  if (!looseInstanceOf(request, Request)) {
1857
1843
  throw new TypeError('"request" must be an instance of Request');
@@ -1860,7 +1846,7 @@ export async function experimental_validateJwtAccessToken(as, request, expectedA
1860
1846
  throw new OPE('"expectedAudience" must be a non-empty string');
1861
1847
  }
1862
1848
  const authorization = request.headers.get('authorization');
1863
- if (!authorization) {
1849
+ if (authorization === null) {
1864
1850
  throw new OPE('"request" is missing an Authorization HTTP Header');
1865
1851
  }
1866
1852
  let { 0: scheme, 1: accessToken, length } = authorization.split(' ');
@@ -1915,7 +1901,13 @@ export async function experimental_validateJwtAccessToken(as, request, expectedA
1915
1901
  scheme === 'dpop' ||
1916
1902
  claims.cnf?.jkt !== undefined ||
1917
1903
  request.headers.has('dpop')) {
1918
- await validateDPoP(as, request, claims, options);
1904
+ await validateDPoP(as, request, accessToken, claims, options);
1919
1905
  }
1920
1906
  return claims;
1921
1907
  }
1908
+ export const experimentalCustomFetch = customFetch;
1909
+ export const experimental_customFetch = customFetch;
1910
+ export const experimentalUseMtlsAlias = useMtlsAlias;
1911
+ export const experimental_useMtlsAlias = useMtlsAlias;
1912
+ export const experimental_validateDetachedSignatureResponse = validateDetachedSignatureResponse;
1913
+ export const experimental_validateJwtAccessToken = validateJwtAccessToken;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oauth4webapi",
3
- "version": "2.8.1",
3
+ "version": "2.10.0",
4
4
  "description": "OAuth 2 / OpenID Connect for JavaScript Runtimes",
5
5
  "keywords": [
6
6
  "access token",
@@ -67,20 +67,20 @@
67
67
  "devDependencies": {
68
68
  "@koa/cors": "^5.0.0",
69
69
  "@types/koa__cors": "^5.0.0",
70
- "@types/node": "^20.11.6",
70
+ "@types/node": "^20.11.16",
71
71
  "@types/oidc-provider": "^8.4.3",
72
72
  "@types/qunit": "^2.19.10",
73
73
  "archiver": "^6.0.1",
74
74
  "ava": "^5.3.1",
75
75
  "chrome-launcher": "^1.1.0",
76
76
  "edge-runtime": "^2.5.8",
77
- "esbuild": "^0.19.12",
78
- "jose": "^5.2.0",
77
+ "esbuild": "^0.20.0",
78
+ "jose": "^5.2.1",
79
79
  "oidc-provider": "^8.4.5",
80
80
  "patch-package": "^8.0.0",
81
- "prettier": "^3.2.4",
81
+ "prettier": "^3.2.5",
82
82
  "prettier-plugin-jsdoc": "^1.3.0",
83
- "puppeteer-core": "^21.7.0",
83
+ "puppeteer-core": "^21.11.0",
84
84
  "qunit": "^2.20.0",
85
85
  "raw-body": "^2.5.2",
86
86
  "selfsigned": "^2.4.1",
@@ -88,7 +88,7 @@
88
88
  "tsx": "^4.7.0",
89
89
  "typedoc": "^0.25.7",
90
90
  "typedoc-plugin-markdown": "^3.17.1",
91
- "typedoc-plugin-mdn-links": "^3.1.13",
91
+ "typedoc-plugin-mdn-links": "^3.1.15",
92
92
  "typescript": "^5.3.3",
93
93
  "undici": "^5.28.2"
94
94
  }