oauth4webapi 2.2.4 → 2.4.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
@@ -1,13 +1,13 @@
1
- # OAuth 2 / OpenID Connect for Web Platform API JavaScript runtimes
1
+ # OAuth 2 / OpenID Connect for JavaScript Runtimes
2
2
 
3
- This software is a collection of routines upon which framework-specific client modules may be written. Its objective is to support and, where possible, enforce secure and current best practices using only capabilities common to Browser and Non-Browser JavaScript-based runtime environments.
3
+ This software provides a collection of routines that can be used to build client modules for OAuth 2.1, OAuth 2.0 with the latest Security Best Current Practices (BCP), and FAPI 2.0, as well as OpenID Connect where applicable. The primary goal of this software is to promote secure and up-to-date best practices while using only the capabilities common to both browser and non-browser JavaScript runtimes.
4
4
 
5
- Target profiles of this software are OAuth 2.1, OAuth 2.0 complemented by the latest Security BCP, and FAPI 2.0. Where applicable OpenID Connect is also supported.
5
+ ## Features
6
6
 
7
- ## In Scope & Implemented
7
+ The following features are currently in scope and implemented in this software:
8
8
 
9
9
  - Authorization Server Metadata discovery
10
- - Authorization Code Flow (profiled under OpenID Connect 1.0, OAuth 2.0, OAuth 2.1, and FAPI 2.0), PKCE
10
+ - Authorization Code Flow (profiled under OpenID Connect 1.0, OAuth 2.0, OAuth 2.1, and FAPI 2.0), with PKCE
11
11
  - Refresh Token, Device Authorization, and Client Credentials Grants
12
12
  - Demonstrating Proof-of-Possession at the Application Layer (DPoP)
13
13
  - Token Introspection and Revocation
@@ -26,6 +26,8 @@ Target profiles of this software are OAuth 2.1, OAuth 2.0 complemented by the la
26
26
 
27
27
  ## Dependencies: 0
28
28
 
29
+ `oauth4webapi` has no dependencies and it exports tree-shakeable ESM.
30
+
29
31
  ## [Documentation](docs/README.md)
30
32
 
31
33
  ## [Examples](examples/README.md)
@@ -39,7 +41,7 @@ import * as oauth2 from 'oauth4webapi'
39
41
  **`example`** Deno import
40
42
 
41
43
  ```js
42
- import * as oauth2 from 'https://deno.land/x/oauth4webapi@v2.2.4/mod.ts'
44
+ import * as oauth2 from 'https://deno.land/x/oauth4webapi@v2.4.0/mod.ts'
43
45
  ```
44
46
 
45
47
  - Authorization Code Flow - OpenID Connect [source](examples/code.ts), or plain OAuth 2 [source](examples/oauth.ts)
@@ -54,9 +56,8 @@ import * as oauth2 from 'https://deno.land/x/oauth4webapi@v2.2.4/mod.ts'
54
56
 
55
57
  ## Supported Runtimes
56
58
 
57
- The supported JavaScript runtimes include ones that support the utilized Web API globals and standard built-in objects
59
+ The supported JavaScript runtimes include those that support the utilized Web API globals and standard built-in objects. These are _(but are not limited to)_:
58
60
 
59
- These are _(this is not an exhaustive list)_:
60
61
  - Browsers
61
62
  - Bun
62
63
  - Cloudflare Workers
@@ -67,6 +68,8 @@ These are _(this is not an exhaustive list)_:
67
68
 
68
69
  ## Out of scope
69
70
 
71
+ The following features are currently out of scope:
72
+
70
73
  - CommonJS
71
74
  - Implicit, Hybrid, and Resource Owner Password Credentials Flows
72
75
  - Mutual-TLS Client Authentication and Certificate-Bound Access Tokens
package/build/index.d.ts CHANGED
@@ -48,41 +48,37 @@ export type ClientAuthenticationMethod = 'client_secret_basic' | 'client_secret_
48
48
  * @example CryptoKey algorithm for the `PS256`, `PS384`, or `PS512` JWS Algorithm Identifiers
49
49
  *
50
50
  * ```ts
51
- * interface RSAPSSAlgorithm extends RsaHashedKeyAlgorithm {
51
+ * interface PS256 extends RsaHashedKeyAlgorithm {
52
52
  * name: 'RSA-PSS'
53
- * hash: { name: 'SHA-256' | 'SHA-384' | 'SHA-512' }
53
+ * hash: 'SHA-256'
54
54
  * }
55
55
  *
56
- * interface PS256 extends RSAPSSAlgorithm {
57
- * hash: { name: 'SHA-256' }
58
- * }
59
- *
60
- * interface PS384 extends RSAPSSAlgorithm {
61
- * hash: { name: 'SHA-384' }
56
+ * interface PS384 extends RsaHashedKeyAlgorithm {
57
+ * name: 'RSA-PSS'
58
+ * hash: 'SHA-384'
62
59
  * }
63
60
  *
64
- * interface PS512 extends RSAPSSAlgorithm {
65
- * hash: { name: 'SHA-512' }
61
+ * interface PS512 extends RsaHashedKeyAlgorithm {
62
+ * name: 'RSA-PSS'
63
+ * hash: 'SHA-512'
66
64
  * }
67
65
  * ```
68
66
  *
69
67
  * @example CryptoKey algorithm for the `ES256`, `ES384`, or `ES512` JWS Algorithm Identifiers
70
68
  *
71
69
  * ```ts
72
- * interface ECDSAAlgorithm extends EcKeyAlgorithm {
70
+ * interface ES256 extends EcKeyAlgorithm {
73
71
  * name: 'ECDSA'
74
- * namedCurve: 'P-256' | 'P-384' | 'P-521'
75
- * }
76
- *
77
- * interface ES256 extends ECDSAAlgorithm {
78
72
  * namedCurve: 'P-256'
79
73
  * }
80
74
  *
81
- * interface ES384 extends ECDSAAlgorithm {
75
+ * interface ES384 extends EcKeyAlgorithm {
76
+ * name: 'ECDSA'
82
77
  * namedCurve: 'P-384'
83
78
  * }
84
79
  *
85
- * interface ES512 extends ECDSAAlgorithm {
80
+ * interface ES512 extends EcKeyAlgorithm {
81
+ * name: 'ECDSA'
86
82
  * namedCurve: 'P-521'
87
83
  * }
88
84
  * ```
@@ -90,21 +86,19 @@ export type ClientAuthenticationMethod = 'client_secret_basic' | 'client_secret_
90
86
  * @example CryptoKey algorithm for the `RS256`, `RS384`, or `RS512` JWS Algorithm Identifiers
91
87
  *
92
88
  * ```ts
93
- * interface ECDSAAlgorithm extends RsaHashedKeyAlgorithm {
89
+ * interface RS256 extends RsaHashedKeyAlgorithm {
94
90
  * name: 'RSASSA-PKCS1-v1_5'
95
- * hash: { name: 'SHA-256' | 'SHA-384' | 'SHA-512' }
96
- * }
97
- *
98
- * interface RS256 extends ECDSAAlgorithm {
99
- * hash: { name: 'SHA-256' }
91
+ * hash: 'SHA-256'
100
92
  * }
101
93
  *
102
- * interface RS384 extends ECDSAAlgorithm {
103
- * hash: { name: 'SHA-384' }
94
+ * interface RS384 extends RsaHashedKeyAlgorithm {
95
+ * name: 'RSASSA-PKCS1-v1_5'
96
+ * hash: 'SHA-384'
104
97
  * }
105
98
  *
106
- * interface RS512 extends ECDSAAlgorithm {
107
- * hash: { name: 'SHA-512' }
99
+ * interface RS512 extends RsaHashedKeyAlgorithm {
100
+ * name: 'RSASSA-PKCS1-v1_5'
101
+ * hash: 'SHA-512'
108
102
  * }
109
103
  * ```
110
104
  *
@@ -496,7 +490,9 @@ export declare class UnsupportedOperationError extends Error {
496
490
  constructor(message?: string);
497
491
  }
498
492
  export declare class OperationProcessingError extends Error {
499
- constructor(message: string);
493
+ constructor(message: string, options?: {
494
+ cause?: unknown;
495
+ });
500
496
  }
501
497
  export interface HttpRequestOptions {
502
498
  /**
@@ -613,7 +609,7 @@ export interface PushedAuthorizationRequestOptions extends HttpRequestOptions, A
613
609
  *
614
610
  * @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)
615
611
  */
616
- export declare function issueRequestObject(as: AuthorizationServer, client: Client, parameters: URLSearchParams, privateKey: CryptoKey | PrivateKey): Promise<string>;
612
+ export declare function issueRequestObject(as: AuthorizationServer, client: Client, parameters: URLSearchParams | Record<string, string> | string[][], privateKey: CryptoKey | PrivateKey): Promise<string>;
617
613
  /**
618
614
  * Performs a Pushed Authorization Request at the
619
615
  * {@link AuthorizationServer.pushed_authorization_request_endpoint `as.pushed_authorization_request_endpoint`}.
@@ -623,9 +619,9 @@ export declare function issueRequestObject(as: AuthorizationServer, client: Clie
623
619
  * @param parameters Authorization Request parameters.
624
620
  *
625
621
  * @see [RFC 9126 - OAuth 2.0 Pushed Authorization Requests](https://www.rfc-editor.org/rfc/rfc9126.html#name-pushed-authorization-reques)
626
- * @see [draft-ietf-oauth-dpop-16 - OAuth 2.0 Demonstrating Proof-of-Possession at the Application Layer (DPoP)](https://www.ietf.org/archive/id/draft-ietf-oauth-dpop-16.html#name-dpop-with-pushed-authorizat)
622
+ * @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)
627
623
  */
628
- export declare function pushedAuthorizationRequest(as: AuthorizationServer, client: Client, parameters: URLSearchParams, options?: PushedAuthorizationRequestOptions): Promise<Response>;
624
+ export declare function pushedAuthorizationRequest(as: AuthorizationServer, client: Client, parameters: URLSearchParams | Record<string, string> | string[][], options?: PushedAuthorizationRequestOptions): Promise<Response>;
629
625
  export interface PushedAuthorizationResponse {
630
626
  readonly request_uri: string;
631
627
  readonly expires_in: number;
@@ -674,6 +670,7 @@ export declare function parseWwwAuthenticateChallenges(response: Response): WWWA
674
670
  * @returns Resolves with an object representing the parsed successful response, or an object
675
671
  * representing an OAuth 2.0 protocol style error. Use {@link isOAuth2Error} to determine if an
676
672
  * OAuth 2.0 error was returned.
673
+ *
677
674
  * @see [RFC 9126 - OAuth 2.0 Pushed Authorization Requests](https://www.rfc-editor.org/rfc/rfc9126.html#name-pushed-authorization-reques)
678
675
  */
679
676
  export declare function processPushedAuthorizationResponse(as: AuthorizationServer, client: Client, response: Response): Promise<PushedAuthorizationResponse | OAuth2Error>;
@@ -701,7 +698,7 @@ export interface ProtectedResourceRequestOptions extends Omit<HttpRequestOptions
701
698
  * @param body Request body compatible with the Fetch API and the request's method.
702
699
  *
703
700
  * @see [RFC 6750 - The OAuth 2.0 Authorization Framework: Bearer Token Usage](https://www.rfc-editor.org/rfc/rfc6750.html#section-2.1)
704
- * @see [draft-ietf-oauth-dpop-16 - OAuth 2.0 Demonstrating Proof-of-Possession at the Application Layer (DPoP)](https://www.ietf.org/archive/id/draft-ietf-oauth-dpop-16.html#name-protected-resource-access)
701
+ * @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)
705
702
  */
706
703
  export declare function protectedResourceRequest(accessToken: string, method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | string, url: URL, headers: Headers, body: RequestInit['body'], options?: ProtectedResourceRequestOptions): Promise<Response>;
707
704
  export interface UserInfoRequestOptions extends HttpRequestOptions, DPoPRequestOptions {
@@ -717,7 +714,7 @@ export interface UserInfoRequestOptions extends HttpRequestOptions, DPoPRequestO
717
714
  * @param accessToken Access Token value.
718
715
  *
719
716
  * @see [OpenID Connect Core 1.0](https://openid.net/specs/openid-connect-core-1_0.html#UserInfo)
720
- * @see [draft-ietf-oauth-dpop-16 - OAuth 2.0 Demonstrating Proof-of-Possession at the Application Layer (DPoP)](https://www.ietf.org/archive/id/draft-ietf-oauth-dpop-16.html#name-protected-resource-access)
717
+ * @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)
721
718
  */
722
719
  export declare function userInfoRequest(as: AuthorizationServer, client: Client, accessToken: string, options?: UserInfoRequestOptions): Promise<Response>;
723
720
  export interface UserInfoAddress {
@@ -774,12 +771,13 @@ export declare const skipSubjectCheck: unique symbol;
774
771
  * @returns Resolves with an object representing the parsed successful response, or an object
775
772
  * representing an OAuth 2.0 protocol style error. Use {@link isOAuth2Error} to determine if an
776
773
  * OAuth 2.0 error was returned.
774
+ *
777
775
  * @see [OpenID Connect Core 1.0](https://openid.net/specs/openid-connect-core-1_0.html#UserInfo)
778
776
  */
779
777
  export declare function processUserInfoResponse(as: AuthorizationServer, client: Client, expectedSubject: string | typeof skipSubjectCheck, response: Response): Promise<UserInfoResponse>;
780
778
  export interface TokenEndpointRequestOptions extends HttpRequestOptions, AuthenticatedRequestOptions, DPoPRequestOptions {
781
779
  /** Any additional parameters to send. This cannot override existing parameter values. */
782
- additionalParameters?: URLSearchParams;
780
+ additionalParameters?: URLSearchParams | Record<string, string> | string[][];
783
781
  }
784
782
  /**
785
783
  * Performs a Refresh Token Grant request at the
@@ -791,7 +789,7 @@ export interface TokenEndpointRequestOptions extends HttpRequestOptions, Authent
791
789
  *
792
790
  * @see [RFC 6749 - The OAuth 2.0 Authorization Framework](https://www.rfc-editor.org/rfc/rfc6749.html#section-6)
793
791
  * @see [OpenID Connect Core 1.0](https://openid.net/specs/openid-connect-core-1_0.html#RefreshTokens)
794
- * @see [draft-ietf-oauth-dpop-16 - OAuth 2.0 Demonstrating Proof-of-Possession at the Application Layer (DPoP)](https://www.ietf.org/archive/id/draft-ietf-oauth-dpop-16.html#name-dpop-access-token-request)
792
+ * @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)
795
793
  */
796
794
  export declare function refreshTokenGrantRequest(as: AuthorizationServer, client: Client, refreshToken: string, options?: TokenEndpointRequestOptions): Promise<Response>;
797
795
  /**
@@ -823,6 +821,7 @@ export declare function getValidatedIdTokenClaims(ref: TokenEndpointResponse): I
823
821
  * @returns Resolves with an object representing the parsed successful response, or an object
824
822
  * representing an OAuth 2.0 protocol style error. Use {@link isOAuth2Error} to determine if an
825
823
  * OAuth 2.0 error was returned.
824
+ *
826
825
  * @see [RFC 6749 - The OAuth 2.0 Authorization Framework](https://www.rfc-editor.org/rfc/rfc6749.html#section-6)
827
826
  * @see [OpenID Connect Core 1.0](https://openid.net/specs/openid-connect-core-1_0.html#RefreshTokens)
828
827
  */
@@ -841,7 +840,7 @@ export declare function processRefreshTokenResponse(as: AuthorizationServer, cli
841
840
  * @see [RFC 6749 - The OAuth 2.0 Authorization Framework](https://www.rfc-editor.org/rfc/rfc6749.html#section-4.1)
842
841
  * @see [OpenID Connect Core 1.0](https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth)
843
842
  * @see [RFC 7636 - Proof Key for Code Exchange by OAuth Public Clients (PKCE)](https://www.rfc-editor.org/rfc/rfc7636.html#section-4)
844
- * @see [draft-ietf-oauth-dpop-16 - OAuth 2.0 Demonstrating Proof-of-Possession at the Application Layer (DPoP)](https://www.ietf.org/archive/id/draft-ietf-oauth-dpop-16.html#name-dpop-access-token-request)
843
+ * @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)
845
844
  */
846
845
  export declare function authorizationCodeGrantRequest(as: AuthorizationServer, client: Client, callbackParameters: URLSearchParams, redirectUri: string, codeVerifier: string, options?: TokenEndpointRequestOptions): Promise<Response>;
847
846
  interface JWTPayload {
@@ -930,6 +929,7 @@ export declare const skipAuthTimeCheck: unique symbol;
930
929
  * @returns Resolves with an object representing the parsed successful response, or an object
931
930
  * representing an OAuth 2.0 protocol style error. Use {@link isOAuth2Error} to determine if an
932
931
  * OAuth 2.0 error was returned.
932
+ *
933
933
  * @see [RFC 6749 - The OAuth 2.0 Authorization Framework](https://www.rfc-editor.org/rfc/rfc6749.html#section-4.1)
934
934
  * @see [OpenID Connect Core 1.0](https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth)
935
935
  */
@@ -945,6 +945,7 @@ export declare function processAuthorizationCodeOpenIDResponse(as: Authorization
945
945
  * @returns Resolves with an object representing the parsed successful response, or an object
946
946
  * representing an OAuth 2.0 protocol style error. Use {@link isOAuth2Error} to determine if an
947
947
  * OAuth 2.0 error was returned.
948
+ *
948
949
  * @see [RFC 6749 - The OAuth 2.0 Authorization Framework](https://www.rfc-editor.org/rfc/rfc6749.html#section-4.1)
949
950
  */
950
951
  export declare function processAuthorizationCodeOAuth2Response(as: AuthorizationServer, client: Client, response: Response): Promise<OAuth2TokenEndpointResponse | OAuth2Error>;
@@ -958,9 +959,9 @@ export interface ClientCredentialsGrantRequestOptions extends HttpRequestOptions
958
959
  * @param client Client Metadata.
959
960
  *
960
961
  * @see [RFC 6749 - The OAuth 2.0 Authorization Framework](https://www.rfc-editor.org/rfc/rfc6749.html#section-4.4)
961
- * @see [draft-ietf-oauth-dpop-16 - OAuth 2.0 Demonstrating Proof-of-Possession at the Application Layer (DPoP)](https://www.ietf.org/archive/id/draft-ietf-oauth-dpop-16.html#name-dpop-access-token-request)
962
+ * @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)
962
963
  */
963
- export declare function clientCredentialsGrantRequest(as: AuthorizationServer, client: Client, parameters: URLSearchParams, options?: ClientCredentialsGrantRequestOptions): Promise<Response>;
964
+ export declare function clientCredentialsGrantRequest(as: AuthorizationServer, client: Client, parameters: URLSearchParams | Record<string, string> | string[][], options?: ClientCredentialsGrantRequestOptions): Promise<Response>;
964
965
  /**
965
966
  * Validates Client Credentials Grant Response instance to be one coming from the
966
967
  * {@link AuthorizationServer.token_endpoint `as.token_endpoint`}.
@@ -972,12 +973,13 @@ export declare function clientCredentialsGrantRequest(as: AuthorizationServer, c
972
973
  * @returns Resolves with an object representing the parsed successful response, or an object
973
974
  * representing an OAuth 2.0 protocol style error. Use {@link isOAuth2Error} to determine if an
974
975
  * OAuth 2.0 error was returned.
976
+ *
975
977
  * @see [RFC 6749 - The OAuth 2.0 Authorization Framework](https://www.rfc-editor.org/rfc/rfc6749.html#section-4.4)
976
978
  */
977
979
  export declare function processClientCredentialsResponse(as: AuthorizationServer, client: Client, response: Response): Promise<ClientCredentialsGrantResponse | OAuth2Error>;
978
980
  export interface RevocationRequestOptions extends HttpRequestOptions, AuthenticatedRequestOptions {
979
981
  /** Any additional parameters to send. This cannot override existing parameter values. */
980
- additionalParameters?: URLSearchParams;
982
+ additionalParameters?: URLSearchParams | Record<string, string> | string[][];
981
983
  }
982
984
  /**
983
985
  * Performs a Revocation Request at the
@@ -987,6 +989,7 @@ export interface RevocationRequestOptions extends HttpRequestOptions, Authentica
987
989
  * @param client Client Metadata.
988
990
  * @param token Token to revoke. You can provide the `token_type_hint` parameter via
989
991
  * {@link RevocationRequestOptions.additionalParameters options}.
992
+ *
990
993
  * @see [RFC 7009 - OAuth 2.0 Token Revocation](https://www.rfc-editor.org/rfc/rfc7009.html#section-2)
991
994
  */
992
995
  export declare function revocationRequest(as: AuthorizationServer, client: Client, token: string, options?: RevocationRequestOptions): Promise<Response>;
@@ -998,12 +1001,13 @@ export declare function revocationRequest(as: AuthorizationServer, client: Clien
998
1001
  *
999
1002
  * @returns Resolves with `undefined` when the request was successful, or an object representing an
1000
1003
  * OAuth 2.0 protocol style error.
1004
+ *
1001
1005
  * @see [RFC 7009 - OAuth 2.0 Token Revocation](https://www.rfc-editor.org/rfc/rfc7009.html#section-2)
1002
1006
  */
1003
1007
  export declare function processRevocationResponse(response: Response): Promise<undefined | OAuth2Error>;
1004
1008
  export interface IntrospectionRequestOptions extends HttpRequestOptions, AuthenticatedRequestOptions {
1005
1009
  /** Any additional parameters to send. This cannot override existing parameter values. */
1006
- additionalParameters?: URLSearchParams;
1010
+ additionalParameters?: URLSearchParams | Record<string, string> | string[][];
1007
1011
  /**
1008
1012
  * Request a JWT Response from the
1009
1013
  * {@link AuthorizationServer.introspection_endpoint `as.introspection_endpoint`}. Default is
@@ -1023,6 +1027,7 @@ export interface IntrospectionRequestOptions extends HttpRequestOptions, Authent
1023
1027
  * @param client Client Metadata.
1024
1028
  * @param token Token to introspect. You can provide the `token_type_hint` parameter via
1025
1029
  * {@link IntrospectionRequestOptions.additionalParameters options}.
1030
+ *
1026
1031
  * @see [RFC 7662 - OAuth 2.0 Token Introspection](https://www.rfc-editor.org/rfc/rfc7662.html#section-2)
1027
1032
  * @see [draft-ietf-oauth-jwt-introspection-response-12 - JWT Response for OAuth Token Introspection](https://www.ietf.org/archive/id/draft-ietf-oauth-jwt-introspection-response-12.html#section-4)
1028
1033
  */
@@ -1060,6 +1065,7 @@ export interface IntrospectionResponse {
1060
1065
  * @returns Resolves with an object representing the parsed successful response, or an object
1061
1066
  * representing an OAuth 2.0 protocol style error. Use {@link isOAuth2Error} to determine if an
1062
1067
  * OAuth 2.0 error was returned.
1068
+ *
1063
1069
  * @see [RFC 7662 - OAuth 2.0 Token Introspection](https://www.rfc-editor.org/rfc/rfc7662.html#section-2)
1064
1070
  * @see [draft-ietf-oauth-jwt-introspection-response-12 - JWT Response for OAuth Token Introspection](https://www.ietf.org/archive/id/draft-ietf-oauth-jwt-introspection-response-12.html#section-5)
1065
1071
  */
@@ -1123,7 +1129,7 @@ export interface DeviceAuthorizationRequestOptions extends HttpRequestOptions, A
1123
1129
  *
1124
1130
  * @see [RFC 8628 - OAuth 2.0 Device Authorization Grant](https://www.rfc-editor.org/rfc/rfc8628.html#section-3.1)
1125
1131
  */
1126
- export declare function deviceAuthorizationRequest(as: AuthorizationServer, client: Client, parameters: URLSearchParams, options?: DeviceAuthorizationRequestOptions): Promise<Response>;
1132
+ export declare function deviceAuthorizationRequest(as: AuthorizationServer, client: Client, parameters: URLSearchParams | Record<string, string> | string[][], options?: DeviceAuthorizationRequestOptions): Promise<Response>;
1127
1133
  export interface DeviceAuthorizationResponse {
1128
1134
  readonly device_code: string;
1129
1135
  readonly user_code: string;
@@ -1144,6 +1150,7 @@ export interface DeviceAuthorizationResponse {
1144
1150
  * @returns Resolves with an object representing the parsed successful response, or an object
1145
1151
  * representing an OAuth 2.0 protocol style error. Use {@link isOAuth2Error} to determine if an
1146
1152
  * OAuth 2.0 error was returned.
1153
+ *
1147
1154
  * @see [RFC 8628 - OAuth 2.0 Device Authorization Grant](https://www.rfc-editor.org/rfc/rfc8628.html#section-3.1)
1148
1155
  */
1149
1156
  export declare function processDeviceAuthorizationResponse(as: AuthorizationServer, client: Client, response: Response): Promise<DeviceAuthorizationResponse | OAuth2Error>;
@@ -1156,7 +1163,7 @@ export declare function processDeviceAuthorizationResponse(as: AuthorizationServ
1156
1163
  * @param deviceCode Device Code.
1157
1164
  *
1158
1165
  * @see [RFC 8628 - OAuth 2.0 Device Authorization Grant](https://www.rfc-editor.org/rfc/rfc8628.html#section-3.4)
1159
- * @see [draft-ietf-oauth-dpop-16 - OAuth 2.0 Demonstrating Proof-of-Possession at the Application Layer (DPoP)](https://www.ietf.org/archive/id/draft-ietf-oauth-dpop-16.html#name-dpop-access-token-request)
1166
+ * @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)
1160
1167
  */
1161
1168
  export declare function deviceCodeGrantRequest(as: AuthorizationServer, client: Client, deviceCode: string, options?: TokenEndpointRequestOptions): Promise<Response>;
1162
1169
  /**
@@ -1170,6 +1177,7 @@ export declare function deviceCodeGrantRequest(as: AuthorizationServer, client:
1170
1177
  * @returns Resolves with an object representing the parsed successful response, or an object
1171
1178
  * representing an OAuth 2.0 protocol style error. Use {@link isOAuth2Error} to determine if an
1172
1179
  * OAuth 2.0 error was returned.
1180
+ *
1173
1181
  * @see [RFC 8628 - OAuth 2.0 Device Authorization Grant](https://www.rfc-editor.org/rfc/rfc8628.html#section-3.4)
1174
1182
  */
1175
1183
  export declare function processDeviceCodeResponse(as: AuthorizationServer, client: Client, response: Response): Promise<TokenEndpointResponse | OAuth2Error>;
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.2.4';
4
+ const VERSION = 'v2.4.0';
5
5
  USER_AGENT = `${NAME}/${VERSION}`;
6
6
  }
7
7
  export const clockSkew = Symbol();
@@ -34,8 +34,8 @@ function decodeBase64Url(input) {
34
34
  }
35
35
  return bytes;
36
36
  }
37
- catch {
38
- throw new TypeError('The input to be decoded is not correctly encoded.');
37
+ catch (cause) {
38
+ throw new OPE('The input to be decoded is not correctly encoded.', { cause });
39
39
  }
40
40
  }
41
41
  function b64u(input) {
@@ -98,8 +98,8 @@ export class UnsupportedOperationError extends Error {
98
98
  }
99
99
  }
100
100
  export class OperationProcessingError extends Error {
101
- constructor(message) {
102
- super(message);
101
+ constructor(message, options) {
102
+ super(message, options);
103
103
  this.name = this.constructor.name;
104
104
  Error.captureStackTrace?.(this, this.constructor);
105
105
  }
@@ -219,8 +219,8 @@ export async function processDiscoveryResponse(expectedIssuerIdentifier, respons
219
219
  try {
220
220
  json = await response.json();
221
221
  }
222
- catch {
223
- throw new OPE('failed to parse "response" body as JSON');
222
+ catch (cause) {
223
+ throw new OPE('failed to parse "response" body as JSON', { cause });
224
224
  }
225
225
  if (!isJsonObject(json)) {
226
226
  throw new OPE('"response" body must be a top level object');
@@ -249,7 +249,7 @@ export async function calculatePKCECodeChallenge(codeVerifier) {
249
249
  if (!validateString(codeVerifier)) {
250
250
  throw new TypeError('"codeVerifier" must be a non-empty string');
251
251
  }
252
- return b64u(await crypto.subtle.digest({ name: 'SHA-256' }, buf(codeVerifier)));
252
+ return b64u(await crypto.subtle.digest('SHA-256', buf(codeVerifier)));
253
253
  }
254
254
  function getKeyAndKid(input) {
255
255
  if (input instanceof CryptoKey) {
@@ -443,9 +443,6 @@ async function jwt(header, claimsSet, key) {
443
443
  export async function issueRequestObject(as, client, parameters, privateKey) {
444
444
  assertAs(as);
445
445
  assertClient(client);
446
- if (!(parameters instanceof URLSearchParams)) {
447
- throw new TypeError('"parameters" must be an instance of URLSearchParams');
448
- }
449
446
  parameters = new URLSearchParams(parameters);
450
447
  const { key, kid } = getKeyAndKid(privateKey);
451
448
  if (!isPrivateKey(key)) {
@@ -476,8 +473,8 @@ export async function issueRequestObject(as, client, parameters, privateKey) {
476
473
  try {
477
474
  claims.claims = JSON.parse(value);
478
475
  }
479
- catch {
480
- throw new OPE('failed to parse the "claims" parameter as JSON');
476
+ catch (cause) {
477
+ throw new OPE('failed to parse the "claims" parameter as JSON', { cause });
481
478
  }
482
479
  if (!isJsonObject(claims.claims)) {
483
480
  throw new OPE('"claims" parameter must be a top level object');
@@ -514,9 +511,7 @@ async function dpopProofJwt(headers, options, url, htm, clockSkew, accessToken)
514
511
  htm,
515
512
  nonce,
516
513
  htu: `${url.origin}${url.pathname}`,
517
- ath: accessToken
518
- ? b64u(await crypto.subtle.digest({ name: 'SHA-256' }, buf(accessToken)))
519
- : undefined,
514
+ ath: accessToken ? b64u(await crypto.subtle.digest('SHA-256', buf(accessToken))) : undefined,
520
515
  }, privateKey);
521
516
  headers.set('dpop', proof);
522
517
  }
@@ -534,9 +529,6 @@ async function publicJwk(key) {
534
529
  export async function pushedAuthorizationRequest(as, client, parameters, options) {
535
530
  assertAs(as);
536
531
  assertClient(client);
537
- if (!(parameters instanceof URLSearchParams)) {
538
- throw new TypeError('"parameters" must be an instance of URLSearchParams');
539
- }
540
532
  if (typeof as.pushed_authorization_request_endpoint !== 'string') {
541
533
  throw new TypeError('"as.pushed_authorization_request_endpoint" must be a string');
542
534
  }
@@ -633,8 +625,8 @@ export async function processPushedAuthorizationResponse(as, client, response) {
633
625
  try {
634
626
  json = await response.json();
635
627
  }
636
- catch {
637
- throw new OPE('failed to parse "response" body as JSON');
628
+ catch (cause) {
629
+ throw new OPE('failed to parse "response" body as JSON', { cause });
638
630
  }
639
631
  if (!isJsonObject(json)) {
640
632
  throw new OPE('"response" body must be a top level object');
@@ -802,8 +794,8 @@ export async function processUserInfoResponse(as, client, expectedSubject, respo
802
794
  try {
803
795
  json = await response.json();
804
796
  }
805
- catch {
806
- throw new OPE('failed to parse "response" body as JSON');
797
+ catch (cause) {
798
+ throw new OPE('failed to parse "response" body as JSON', { cause });
807
799
  }
808
800
  }
809
801
  if (!isJsonObject(json)) {
@@ -888,8 +880,8 @@ async function processGenericAccessTokenResponse(as, client, response, ignoreIdT
888
880
  try {
889
881
  json = await response.json();
890
882
  }
891
- catch {
892
- throw new OPE('failed to parse "response" body as JSON');
883
+ catch (cause) {
884
+ throw new OPE('failed to parse "response" body as JSON', { cause });
893
885
  }
894
886
  if (!isJsonObject(json)) {
895
887
  throw new OPE('"response" body must be a top level object');
@@ -1173,8 +1165,8 @@ export async function processIntrospectionResponse(as, client, response) {
1173
1165
  try {
1174
1166
  json = await response.json();
1175
1167
  }
1176
- catch {
1177
- throw new OPE('failed to parse "response" body as JSON');
1168
+ catch (cause) {
1169
+ throw new OPE('failed to parse "response" body as JSON', { cause });
1178
1170
  }
1179
1171
  if (!isJsonObject(json)) {
1180
1172
  throw new OPE('"response" body must be a top level object');
@@ -1213,8 +1205,8 @@ async function processJwksResponse(response) {
1213
1205
  try {
1214
1206
  json = await response.json();
1215
1207
  }
1216
- catch {
1217
- throw new OPE('failed to parse "response" body as JSON');
1208
+ catch (cause) {
1209
+ throw new OPE('failed to parse "response" body as JSON', { cause });
1218
1210
  }
1219
1211
  if (!isJsonObject(json)) {
1220
1212
  throw new OPE('"response" body must be a top level object');
@@ -1280,7 +1272,7 @@ function keyToSubtle(key) {
1280
1272
  case 'ECDSA':
1281
1273
  return {
1282
1274
  name: key.algorithm.name,
1283
- hash: { name: ecdsaHashName(key.algorithm.namedCurve) },
1275
+ hash: ecdsaHashName(key.algorithm.namedCurve),
1284
1276
  };
1285
1277
  case 'RSA-PSS': {
1286
1278
  checkRsaKeyAlgorithm(key.algorithm);
@@ -1298,10 +1290,10 @@ function keyToSubtle(key) {
1298
1290
  }
1299
1291
  case 'RSASSA-PKCS1-v1_5':
1300
1292
  checkRsaKeyAlgorithm(key.algorithm);
1301
- return { name: key.algorithm.name };
1293
+ return key.algorithm.name;
1302
1294
  case 'Ed448':
1303
1295
  case 'Ed25519':
1304
- return { name: key.algorithm.name };
1296
+ return key.algorithm.name;
1305
1297
  }
1306
1298
  throw new UnsupportedOperationError();
1307
1299
  }
@@ -1318,8 +1310,8 @@ async function validateJwt(jws, checkAlg, getKey, clockSkew, clockTolerance) {
1318
1310
  try {
1319
1311
  header = JSON.parse(buf(b64u(protectedHeader)));
1320
1312
  }
1321
- catch {
1322
- throw new OPE('failed to parse JWT Header body as base64url encoded JSON');
1313
+ catch (cause) {
1314
+ throw new OPE('failed to parse JWT Header body as base64url encoded JSON', { cause });
1323
1315
  }
1324
1316
  if (!isJsonObject(header)) {
1325
1317
  throw new OPE('JWT Header must be a top level object');
@@ -1341,8 +1333,8 @@ async function validateJwt(jws, checkAlg, getKey, clockSkew, clockTolerance) {
1341
1333
  try {
1342
1334
  claims = JSON.parse(buf(b64u(payload)));
1343
1335
  }
1344
- catch {
1345
- throw new OPE('failed to parse JWT Payload body as base64url encoded JSON');
1336
+ catch (cause) {
1337
+ throw new OPE('failed to parse JWT Payload body as base64url encoded JSON', { cause });
1346
1338
  }
1347
1339
  if (!isJsonObject(claims)) {
1348
1340
  throw new OPE('JWT Payload must be a top level object');
@@ -1495,11 +1487,11 @@ function algToSubtle(alg, crv) {
1495
1487
  case 'PS256':
1496
1488
  case 'PS384':
1497
1489
  case 'PS512':
1498
- return { name: 'RSA-PSS', hash: { name: `SHA-${alg.slice(-3)}` } };
1490
+ return { name: 'RSA-PSS', hash: `SHA-${alg.slice(-3)}` };
1499
1491
  case 'RS256':
1500
1492
  case 'RS384':
1501
1493
  case 'RS512':
1502
- return { name: 'RSASSA-PKCS1-v1_5', hash: { name: `SHA-${alg.slice(-3)}` } };
1494
+ return { name: 'RSASSA-PKCS1-v1_5', hash: `SHA-${alg.slice(-3)}` };
1503
1495
  case 'ES256':
1504
1496
  case 'ES384':
1505
1497
  return { name: 'ECDSA', namedCurve: `P-${alg.slice(-3)}` };
@@ -1508,9 +1500,8 @@ function algToSubtle(alg, crv) {
1508
1500
  case 'EdDSA': {
1509
1501
  switch (crv) {
1510
1502
  case 'Ed25519':
1511
- return { name: 'Ed25519' };
1512
1503
  case 'Ed448':
1513
- return { name: 'Ed448' };
1504
+ return crv;
1514
1505
  default:
1515
1506
  throw new UnsupportedOperationError();
1516
1507
  }
@@ -1526,9 +1517,6 @@ async function importJwk(alg, jwk) {
1526
1517
  export async function deviceAuthorizationRequest(as, client, parameters, options) {
1527
1518
  assertAs(as);
1528
1519
  assertClient(client);
1529
- if (!(parameters instanceof URLSearchParams)) {
1530
- throw new TypeError('"parameters" must be an instance of URLSearchParams');
1531
- }
1532
1520
  if (typeof as.device_authorization_endpoint !== 'string') {
1533
1521
  throw new TypeError('"as.device_authorization_endpoint" must be a string');
1534
1522
  }
@@ -1557,8 +1545,8 @@ export async function processDeviceAuthorizationResponse(as, client, response) {
1557
1545
  try {
1558
1546
  json = await response.json();
1559
1547
  }
1560
- catch {
1561
- throw new OPE('failed to parse "response" body as JSON');
1548
+ catch (cause) {
1549
+ throw new OPE('failed to parse "response" body as JSON', { cause });
1562
1550
  }
1563
1551
  if (!isJsonObject(json)) {
1564
1552
  throw new OPE('"response" body must be a top level object');
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "oauth4webapi",
3
- "version": "2.2.4",
4
- "description": "OAuth 2 / OpenID Connect for Web Platform API JavaScript runtimes",
3
+ "version": "2.4.0",
4
+ "description": "OAuth 2 / OpenID Connect for JavaScript Runtimes",
5
5
  "keywords": [
6
6
  "auth",
7
7
  "authentication",
@@ -28,6 +28,7 @@
28
28
  "openid-connect",
29
29
  "openid",
30
30
  "vercel",
31
+ "workerd",
31
32
  "workers"
32
33
  ],
33
34
  "homepage": "https://github.com/panva/oauth4webapi",
@@ -58,26 +59,26 @@
58
59
  "tap:edge-runtime": "./tap/.edge-runtime.sh",
59
60
  "tap:electron": "./tap/.electron.sh",
60
61
  "tap:node": "bash -c './tap/.node.sh'",
61
- "tap:workers": "./tap/.workers.sh",
62
+ "tap:workerd": "./tap/.workerd.sh",
62
63
  "test": "bash -c 'source .node_flags.sh && ava'"
63
64
  },
64
65
  "devDependencies": {
65
- "@esbuild-kit/esm-loader": "^2.5.5",
66
- "@types/node": "^18.16.0",
67
- "@types/qunit": "^2.19.4",
68
- "ava": "^5.2.0",
69
- "edge-runtime": "^2.1.4",
70
- "esbuild": "^0.17.18",
71
- "jose": "^4.14.1",
72
- "patch-package": "^6.5.1",
73
- "prettier": "^2.8.8",
74
- "prettier-plugin-jsdoc": "^0.4.2",
75
- "qunit": "^2.19.4",
76
- "timekeeper": "^2.2.0",
77
- "typedoc": "^0.24.6",
78
- "typedoc-plugin-markdown": "^3.15.2",
79
- "typedoc-plugin-mdn-links": "^3.0.3",
80
- "typescript": "^5.0.4",
81
- "undici": "^5.22.0"
66
+ "@esbuild-kit/esm-loader": "^2.6.5",
67
+ "@types/node": "^20.9.0",
68
+ "@types/qunit": "^2.19.8",
69
+ "ava": "^5.3.1",
70
+ "edge-runtime": "^2.5.7",
71
+ "esbuild": "^0.19.5",
72
+ "jose": "^5.1.1",
73
+ "patch-package": "^8.0.0",
74
+ "prettier": "^3.1.0",
75
+ "prettier-plugin-jsdoc": "^1.1.1",
76
+ "qunit": "^2.20.0",
77
+ "timekeeper": "^2.3.1",
78
+ "typedoc": "^0.25.3",
79
+ "typedoc-plugin-markdown": "^3.17.1",
80
+ "typedoc-plugin-mdn-links": "^3.1.0",
81
+ "typescript": "^5.2.2",
82
+ "undici": "^5.27.2"
82
83
  }
83
84
  }