openid-client 5.6.5 β†’ 6.0.0-beta.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,323 +1,226 @@
1
- # openid-client
2
-
3
- openid-client is a server side [OpenID][openid-connect] Relying Party (RP, Client) implementation for
4
- Node.js runtime, supports [passport][passport-url].
5
-
6
- ## Implemented specs & features
7
-
8
- The following client/RP features from OpenID Connect/OAuth2.0 specifications are implemented by
9
- openid-client.
10
-
11
- - [OpenID Connect Core 1.0][feature-core]
12
- - Authorization Callback
13
- - Authorization Code Flow
14
- - Implicit Flow
15
- - Hybrid Flow
16
- - UserInfo Request
17
- - Offline Access / Refresh Token Grant
18
- - Client Credentials Grant
19
- - Client Authentication
20
- - none
21
- - client_secret_basic
22
- - client_secret_post
23
- - client_secret_jwt
24
- - private_key_jwt
25
- - Consuming Self-Issued OpenID Provider ID Token response
26
- - [OpenID Connect Discovery 1.0][feature-discovery]
27
- - Discovery of OpenID Provider (Issuer) Metadata
28
- - Discovery of OpenID Provider (Issuer) Metadata via user provided inputs (via [webfinger][documentation-webfinger])
29
- - [OpenID Connect Dynamic Client Registration 1.0][feature-registration]
30
- - Dynamic Client Registration request
31
- - Client initialization via registration client uri
32
- - [RFC7009 - OAuth 2.0 Token revocation][feature-revocation]
33
- - Client Authenticated request to token revocation
34
- - [RFC7662 - OAuth 2.0 Token introspection][feature-introspection]
35
- - Client Authenticated request to token introspection
36
- - [RFC8628 - OAuth 2.0 Device Authorization Grant (Device Flow)][feature-device-flow]
37
- - [RFC8705 - OAuth 2.0 Mutual TLS Client Authentication and Certificate-Bound Access Tokens][feature-mtls]
38
- - Mutual TLS Client Certificate-Bound Access Tokens
39
- - Metadata for Mutual TLS Endpoint Aliases
40
- - Client Authentication
41
- - tls_client_auth
42
- - self_signed_tls_client_auth
43
- - [RFC9101 - OAuth 2.0 JWT-Secured Authorization Request (JAR)][feature-jar]
44
- - [RFC9126 - OAuth 2.0 Pushed Authorization Requests (PAR)][feature-par]
45
- - [RFC9449 - OAuth 2.0 Demonstration of Proof-of-Possession at the Application Layer (DPoP)][feature-dpop]
46
- - [OpenID Connect RP-Initiated Logout 1.0][feature-rp-logout]
47
- - [Financial-grade API Security Profile 1.0 - Part 2: Advanced (FAPI)][feature-fapi]
48
- - [JWT Secured Authorization Response Mode for OAuth 2.0 (JARM)][feature-jarm]
49
- - [OAuth 2.0 Authorization Server Issuer Identification][feature-iss]
50
-
51
- Updates to draft specifications are released as MINOR library versions,
52
- if you utilize these specification implementations consider using the tilde `~` operator in your
53
- package.json since breaking changes may be introduced as part of these version updates.
54
-
55
- ## Certification
56
- [<img width="184" height="96" align="right" src="https://cdn.jsdelivr.net/gh/panva/node-openid-client@38cf016b0837e6d4116de3780b28d222d5780bc9/OpenID_Certified.png" alt="OpenID Certification">][openid-certified-link]
57
- Filip Skokan has [certified][openid-certified-link] that [openid-client][npm-url]
58
- conforms to the following profiles of the OpenID Connectβ„’ protocol
59
-
60
- - Basic, Implicit, Hybrid, Config, Dynamic, and Form Post RP
61
- - FAPI 1.0 Advanced RP
1
+ # High-Level OAuth 2 / OpenID Connect Client API for JavaScript Runtimes
62
2
 
63
- ## Sponsor
3
+ TODO
64
4
 
65
- [<img height="65" align="left" src="https://cdn.auth0.com/blog/github-sponsorships/brand-evolution-logo-Auth0-horizontal-Indigo.png" alt="auth0-logo">][sponsor-auth0] If you want to quickly add OpenID Connect authentication to Node.js apps, feel free to check out Auth0's Node.js SDK and free plan. [Create an Auth0 account; it's free!][sponsor-auth0]<br><br>
5
+ ## Features
66
6
 
67
- ## Support
7
+ The following features are currently in scope and implemented in this software:
68
8
 
69
- If you or your business use openid-client, please consider becoming a [sponsor][support-sponsor] so I can continue maintaining it and adding new features carefree.
9
+ - Authorization Server Metadata discovery
10
+ - Authorization Code Flow (profiled under OpenID Connect 1.0, OAuth 2.0, OAuth 2.1, FAPI 1.0 Advanced, and FAPI 2.0)
11
+ - Refresh Token, Device Authorization, and Client Credentials Grants
12
+ - Demonstrating Proof-of-Possession at the Application Layer (DPoP)
13
+ - Token Introspection and Revocation
14
+ - Pushed Authorization Requests (PAR)
15
+ - UserInfo and Protected Resource Requests
16
+ - Authorization Server Issuer Identification
17
+ - JWT Secured Introspection, Response Mode (JARM), Authorization Request (JAR), and UserInfo
70
18
 
19
+ ## Sponsor
71
20
 
72
- ## Documentation
21
+ <picture>
22
+ <source media="(prefers-color-scheme: dark)" srcset="./sponsor/Auth0byOkta_dark.png">
23
+ <source media="(prefers-color-scheme: light)" srcset="./sponsor/Auth0byOkta_light.png">
24
+ <img height="65" align="left" alt="Auth0 by Okta" src="./sponsor/Auth0byOkta_light.png">
25
+ </picture>
73
26
 
74
- The library exposes what are essentially steps necessary to be done by a relying party consuming
75
- OpenID Connect Authorization Server responses or wrappers around requests to its endpoints. Aside
76
- from a generic OpenID Connect [passport][passport-url] strategy it does not expose any framework
77
- specific middlewares. Those can however be built using the exposed API, one such example is [express-openid-connect][]
27
+ If you want to quickly add authentication to JavaScript apps, feel free to check out Auth0's JavaScript SDK and free plan. [Create an Auth0 account; it's free!][sponsor-auth0]<br><br>
78
28
 
79
- - [openid-client API Documentation][documentation]
80
- - [Issuer][documentation-issuer]
81
- - [Client][documentation-client]
82
- - [Customizing][documentation-customizing]
83
- - [TokenSet][documentation-tokenset]
84
- - [Strategy][documentation-strategy]
85
- - [generators][documentation-generators]
86
- - [errors][documentation-errors]
29
+ ## [Certification](https://openid.net/certification/faq/)
87
30
 
88
- ## Install
31
+ [<img width="96" height="50" align="right" src="https://user-images.githubusercontent.com/241506/166977513-7cd710a9-7f60-4944-aebe-a658e9f36375.png" alt="OpenID Certification">](#certification)
89
32
 
90
- Node.js LTS releases Codename Erbium and newer LTS releases are supported.
33
+ [Filip Skokan](https://github.com/panva) has [certified](https://openid.net/certification) that [this software](https://github.com/panva/openid-client) conforms to the Basic, FAPI 1.0, and FAPI 2.0 Relying Party Conformance Profiles of the OpenID Connectβ„’ protocol.
91
34
 
92
- ```console
93
- npm install openid-client
94
- ```
35
+ ## [πŸ’— Help the project](https://github.com/sponsors/panva)
95
36
 
96
- Note: Other javascript runtimes are not supported.
97
- I recommend [panva/oauth4webapi][oauth4webapi], or a derivate thereof, if you're
98
- looking for a similarly compliant and certified client software that's not dependent
99
- on the Node.js runtime builtins.
37
+ Support from the community to continue maintaining and improving this module is welcome. If you find the module useful, please consider supporting the project by [becoming a sponsor](https://github.com/sponsors/panva).
100
38
 
101
39
  ## Quick start
102
40
 
103
- Discover an Issuer configuration using its published .well-known endpoints
104
- ```js
105
- import { Issuer } from 'openid-client';
106
-
107
- const googleIssuer = await Issuer.discover('https://accounts.google.com');
108
- console.log('Discovered issuer %s %O', googleIssuer.issuer, googleIssuer.metadata);
41
+ ```ts
42
+ import * as client from 'openid-client'
43
+
44
+ let server!: URL
45
+ let clientId!: string
46
+ let clientSecret!: string
47
+ let config: client.Configuration = await client.discovery(
48
+ server,
49
+ clientId,
50
+ clientSecret,
51
+ )
109
52
  ```
110
53
 
111
54
  ### Authorization Code Flow
112
55
 
113
56
  Authorization Code flow is for obtaining Access Tokens (and optionally Refresh Tokens) to use with
114
- third party APIs securely as well as Refresh Tokens. In this quick start your application also uses
115
- PKCE instead of `state` parameter for CSRF protection.
116
-
117
- Create a Client instance for that issuer's authorization server intended for Authorization Code
118
- flow.
119
-
120
- **See the [documentation][] for full API details.**
121
-
122
- ```js
123
- const client = new googleIssuer.Client({
124
- client_id: 'zELcpfANLqY7Oqas',
125
- client_secret: 'TQV5U29k1gHibH5bx1layBo0OSAvAbRT3UYW3EWrSYBB5swxjVfWUa1BS8lqzxG/0v9wruMcrGadany3',
126
- redirect_uris: ['http://localhost:3000/cb'],
127
- response_types: ['code'],
128
- // id_token_signed_response_alg (default "RS256")
129
- // token_endpoint_auth_method (default "client_secret_basic")
130
- }); // => Client
131
- ```
57
+ third party APIs.
132
58
 
133
- When you want to have your end-users authorize you need to send them to the issuer's
134
- `authorization_endpoint`. Consult the web framework of your choice on how to redirect but here's how
59
+ When you want to have your end-users authorize or authenticate you need to send them to the authorization server's `authorization_endpoint`. Consult the web framework of your choice on how to redirect but here's how
135
60
  to get the authorization endpoint's URL with parameters already encoded in the query to redirect
136
61
  to.
137
62
 
138
- ```js
139
- import { generators } from 'openid-client';
140
- const code_verifier = generators.codeVerifier();
141
- // store the code_verifier in your framework's session mechanism, if it is a cookie based solution
142
- // it should be httpOnly (not readable by javascript) and encrypted.
143
-
144
- const code_challenge = generators.codeChallenge(code_verifier);
145
-
146
- client.authorizationUrl({
147
- scope: 'openid email profile',
148
- resource: 'https://my.api.example.com/resource/32178',
63
+ ```ts
64
+ /**
65
+ * Value used in the authorization request as redirect_uri pre-registered at the
66
+ * Authorization Server.
67
+ */
68
+ let redirect_uri!: string
69
+ let scope!: string
70
+ /**
71
+ * The following MUST be generated for every redirect to the
72
+ * authorization_endpoint. You must store the code_verifier and state in the
73
+ * end-user session such that it can be recovered as the user gets redirected
74
+ * from the authorization server back to your application.
75
+ */
76
+ let code_verifier: string = client.randomPKCECodeVerifier()
77
+ let code_challenge: string =
78
+ await client.calculatePKCECodeChallenge(code_verifier)
79
+ let state!: string
80
+
81
+ let parameters: Record<string, string> = {
82
+ redirect_uri,
83
+ scope,
149
84
  code_challenge,
150
85
  code_challenge_method: 'S256',
151
- });
86
+ }
87
+
88
+ if (
89
+ config.serverMetadata().code_challenge_methods_supported?.includes('S256') !==
90
+ true
91
+ ) {
92
+ /**
93
+ * We cannot be sure the server supports PKCE so we're going to use state too.
94
+ * Use of PKCE is backwards compatible even if the AS doesn't support it which
95
+ * is why we're using it regardless.
96
+ */
97
+ state = client.randomState()
98
+ parameters.state = state
99
+ }
100
+
101
+ let redirectTo: URL = client.buildAuthorizationUrl(config, parameters)
102
+
103
+ // now redirect the user to redirectTo.href
104
+ console.log('redirecting to', redirectTo.href)
152
105
  ```
153
106
 
154
107
  When end-users are redirected back to your `redirect_uri` your application consumes the callback and
155
108
  passes in the `code_verifier` to include it in the authorization code grant token exchange.
156
- ```js
157
- const params = client.callbackParams(req);
158
- const tokenSet = await client.callback('https://client.example.com/callback', params, { code_verifier });
159
- console.log('received and validated tokens %j', tokenSet);
160
- console.log('validated ID Token claims %j', tokenSet.claims());
161
- ```
162
109
 
163
- You can then call the `userinfo_endpoint`.
164
- ```js
165
- const userinfo = await client.userinfo(access_token);
166
- console.log('userinfo %j', userinfo);
167
- ```
110
+ ```ts
111
+ let getCurrentUrl!: (...args: any) => URL
168
112
 
169
- And later refresh the tokenSet if it had a `refresh_token`.
170
- ```js
171
- const tokenSet = await client.refresh(refresh_token);
172
- console.log('refreshed and validated tokens %j', tokenSet);
173
- console.log('refreshed ID Token claims %j', tokenSet.claims());
174
- ```
113
+ let tokens: client.TokenEndpointResponse = await client.authorizationCodeGrant(
114
+ config,
115
+ getCurrentUrl(),
116
+ {
117
+ pkceCodeVerifier: code_verifier,
118
+ expectedState: state,
119
+ },
120
+ )
175
121
 
176
- ### Implicit ID Token Flow
122
+ console.log('Token Endpoint Response', tokens)
123
+ ```
177
124
 
178
- Implicit `response_type=id_token` flow is perfect for simply authenticating your end-users, assuming
179
- the only job you want done is authenticating the user and then relying on your own session mechanism
180
- with no need for accessing any third party APIs with an Access Token from the Authorization Server.
125
+ You can then fetch a protected resource response
181
126
 
182
- Create a Client instance for that issuer's authorization server intended for ID Token implicit flow.
127
+ ```ts
128
+ let protectedResourceResponse: Response = await client.fetchProtectedResource(
129
+ config,
130
+ tokens.access_token,
131
+ new URL('https://rs.example.com/api'),
132
+ 'GET',
133
+ )
183
134
 
184
- **See the [documentation][] for full API details.**
185
- ```js
186
- const client = new googleIssuer.Client({
187
- client_id: 'zELcpfANLqY7Oqas',
188
- redirect_uris: ['http://localhost:3000/cb'],
189
- response_types: ['id_token'],
190
- // id_token_signed_response_alg (default "RS256")
191
- }); // => Client
135
+ console.log(
136
+ 'Protected Resource Response',
137
+ await protectedResourceResponse.json(),
138
+ )
192
139
  ```
193
140
 
194
- When you want to have your end-users authorize you need to send them to the issuer's
195
- `authorization_endpoint`. Consult the web framework of your choice on how to redirect but here's how
196
- to get the authorization endpoint's URL with parameters already encoded in the query to redirect
197
- to.
141
+ ### Device Authorization Grant (Device Flow)
198
142
 
199
- ```js
200
- import { generators } from 'openid-client';
201
- const nonce = generators.nonce();
202
- // store the nonce in your framework's session mechanism, if it is a cookie based solution
203
- // it should be httpOnly (not readable by javascript) and encrypted.
204
-
205
- client.authorizationUrl({
206
- scope: 'openid email profile',
207
- response_mode: 'form_post',
208
- nonce,
209
- });
143
+ ```ts
144
+ let scope!: string
145
+ let response = await client.initiateDeviceAuthorization(config, { scope })
146
+
147
+ console.log('User Code:', response.user_code)
148
+ console.log('Verification URI:', response.verification_uri)
149
+ console.log('Verification URI (complete):', response.verification_uri_complete)
210
150
  ```
211
151
 
212
- When end-users hit back your `redirect_uri` with a POST (authorization request included `form_post`
213
- response mode) your application consumes the callback and passes the `nonce` in to include it in the
214
- ID Token verification steps.
215
- ```js
216
- // assumes req.body is populated from your web framework's body parser
217
- const params = client.callbackParams(req);
218
- const tokenSet = await client.callback('https://client.example.com/callback', params, { nonce });
219
- console.log('received and validated tokens %j', tokenSet);
220
- console.log('validated ID Token claims %j', tokenSet.claims());
152
+ You will display the instructions to the end-user and have them directed at `verification_uri` or
153
+ `verification_uri_complete`, afterwards you can start polling for the Device Access Token Response.
154
+
155
+ ```ts
156
+ let tokens: client.TokenEndpointResponse =
157
+ await client.pollDeviceAuthorizationGrant(config, response)
158
+
159
+ console.log('Token Endpoint Response', tokens)
221
160
  ```
222
161
 
223
- ### Device Authorization Grant (Device Flow)
162
+ This will poll in a regular interval and only resolve with tokens once the end-user authenticates.
163
+
164
+ ### Client Credentials Grant
224
165
 
225
- [RFC8628 - OAuth 2.0 Device Authorization Grant (Device Flow)](https://tools.ietf.org/html/rfc8628)
226
- is started by starting a Device Authorization Request.
166
+ Client Credentials flow is for obtaining Access Tokens to use with third party APIs on behalf of your application, rather than an end-user which was the case in previous examples.
167
+
168
+ ```ts
169
+ let scope!: string
170
+ let resource!: string
227
171
 
228
- ```js
229
- const handle = await client.deviceAuthorization();
230
- console.log('User Code: ', handle.user_code);
231
- console.log('Verification URI: ', handle.verification_uri);
232
- console.log('Verification URI (complete): ', handle.verification_uri_complete);
172
+ let tokens: client.TokenEndpointResponse = await lib.clientCredentialsGrant(
173
+ config,
174
+ { scope, resource },
175
+ )
176
+
177
+ console.log('Token Endpoint Response', tokens)
233
178
  ```
234
179
 
235
- The handle represents a Device Authorization Response with the `verification_uri`, `user_code` and
236
- other defined response properties.
180
+ ## [API Reference](docs/README.md)
237
181
 
238
- You will display the instructions to the end-user and have him directed at `verification_uri` or
239
- `verification_uri_complete`, afterwards you can start polling for the Device Access Token Response.
240
- ```js
241
- const tokenSet = await handle.poll();
242
- console.log('received tokens %j', tokenSet);
182
+ `openid-client` is distributed via [npmjs.com](https://www.npmjs.com/package/openid-client) and [github.com](https://github.com/panva/openid-client).
183
+
184
+ ## [Examples](examples/README.md)
185
+
186
+ **`example`** ESM import
187
+
188
+ ```ts
189
+ import * as client from 'openid-client'
243
190
  ```
244
191
 
245
- This will poll in the defined interval and only resolve with a TokenSet once one is received. This
246
- will handle the defined `authorization_pending` and `slow_down` "soft" errors and continue polling
247
- but upon any other error it will reject. With tokenSet received you can throw away the handle.
192
+ - Authorization Code Flow (OAuth 2.0) - [source](examples/oauth.ts)
193
+ - Authorization Code Flow (OpenID Connect) - [source](examples/oidc.ts) | [diff](examples/oidc.diff)
194
+ - Extensions
195
+ - JWT Secured Authorization Request (JAR) - [source](examples/jar.ts) | [diff](examples/jar.diff)
196
+ - JWT Secured Authorization Response Mode (JARM) - [source](examples/jarm.ts) | [diff](examples/jarm.diff)
197
+ - Pushed Authorization Request (PAR) - [source](examples/par.ts) | [diff](examples/par.diff)
248
198
 
249
- ### Client Credentials Grant Flow
199
+ ## Supported Runtimes
250
200
 
251
- Client Credentials flow is for obtaining Access Tokens to use with third party APIs on behalf of your application, rather than an end-user which was the case in previous examples.
201
+ 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)_:
252
202
 
253
- **See the [documentation](./docs/README.md#clientgrantbody-extras) for full API details.**
203
+ - Browsers
204
+ - Bun
205
+ - Cloudflare Workers
206
+ - Deno
207
+ - Electron
208
+ - Node.js[^nodejs]
209
+ - Vercel's Edge Runtime
254
210
 
255
- ```js
256
- const client = new issuer.Client({
257
- client_id: 'zELcpfANLqY7Oqas',
258
- client_secret: 'TQV5U29k1gHibH5bx1layBo0OSAvAbRT3UYW3EWrSYBB5swxjVfWUa1BS8lqzxG/0v9wruMcrGadany3',
259
- });
211
+ ## Supported Versions
260
212
 
261
- const tokenSet = await client.grant({
262
- resource: 'urn:example:third-party-api',
263
- grant_type: 'client_credentials'
264
- });
265
- ```
213
+ | Version | Security Fixes πŸ”‘ | Other Bug Fixes 🐞 | New Features ⭐ | Runtime and Module type |
214
+ | -------------------------------------------------------- | ----------------- | ------------------ | --------------- | ------------------------------- |
215
+ | [v6.x](https://github.com/panva/openid-client/tree/v6.x) | βœ… | βœ… | βœ… | Universal[^universal] ESM[^cjs] |
216
+ | [v5.x](https://github.com/panva/openid-client/tree/v5.x) | βœ… | ❌ | ❌ | Node.js CJS + ESM |
217
+
218
+ [sponsor-auth0]: https://auth0.com/signup?utm_source=external_sites&utm_medium=panva&utm_campaign=devn_signup
219
+ [WebCryptoAPI]: https://w3c.github.io/webcrypto/
220
+ [Fetch API]: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
221
+
222
+ [^nodejs]: Node.js v20.x as baseline is required
223
+
224
+ [^universal]: Assumes runtime support of [WebCryptoAPI][] and [Fetch API][]
266
225
 
267
- ## FAQ
268
-
269
- #### Semver?
270
-
271
- **Yes.** Everything that's either exported in the TypeScript definitions file or
272
- [documented][documentation] is subject to
273
- [Semantic Versioning 2.0.0](https://semver.org/spec/v2.0.0.html). The rest is to be considered
274
- private API and is subject to change between any versions.
275
-
276
- #### How do I use it outside of Node.js
277
-
278
- It is **only built for Node.js**. Other javascript runtimes are not supported.
279
- I recommend [panva/oauth4webapi][oauth4webapi], or a derivate thereof, if you're
280
- looking for a similarly compliant and certified client software that's not dependent
281
- on the Node.js runtime builtins.
282
-
283
- #### How to make the client send client_id and client_secret in the body?
284
-
285
- See [Client Authentication Methods (docs)][documentation-methods].
286
-
287
- #### Can I adjust the HTTP timeout?
288
-
289
- See [Customizing (docs)][documentation-customizing].
290
-
291
-
292
- [openid-connect]: https://openid.net/connect/
293
- [feature-core]: https://openid.net/specs/openid-connect-core-1_0.html
294
- [feature-discovery]: https://openid.net/specs/openid-connect-discovery-1_0.html
295
- [feature-registration]: https://openid.net/specs/openid-connect-registration-1_0.html
296
- [feature-revocation]: https://tools.ietf.org/html/rfc7009
297
- [feature-introspection]: https://tools.ietf.org/html/rfc7662
298
- [feature-mtls]: https://tools.ietf.org/html/rfc8705
299
- [feature-device-flow]: https://tools.ietf.org/html/rfc8628
300
- [feature-rp-logout]: https://openid.net/specs/openid-connect-rpinitiated-1_0.html
301
- [feature-jarm]: https://openid.net/specs/oauth-v2-jarm.html
302
- [feature-fapi]: https://openid.net/specs/openid-financial-api-part-2-1_0.html
303
- [feature-dpop]: https://www.rfc-editor.org/rfc/rfc9449.html
304
- [feature-par]: https://www.rfc-editor.org/rfc/rfc9126.html
305
- [feature-jar]: https://www.rfc-editor.org/rfc/rfc9101.html
306
- [feature-iss]: https://www.rfc-editor.org/rfc/rfc9207.html
307
- [openid-certified-link]: https://openid.net/certification/
308
- [passport-url]: http://passportjs.org
309
- [npm-url]: https://www.npmjs.com/package/openid-client
310
- [sponsor-auth0]: https://a0.to/try-auth0
311
- [support-sponsor]: https://github.com/sponsors/panva
312
- [documentation]: https://github.com/panva/node-openid-client/blob/main/docs/README.md
313
- [documentation-issuer]: https://github.com/panva/node-openid-client/blob/main/docs/README.md#issuer
314
- [documentation-client]: https://github.com/panva/node-openid-client/blob/main/docs/README.md#client
315
- [documentation-customizing]: https://github.com/panva/node-openid-client/blob/main/docs/README.md#customizing
316
- [documentation-tokenset]: https://github.com/panva/node-openid-client/blob/main/docs/README.md#tokenset
317
- [documentation-strategy]: https://github.com/panva/node-openid-client/blob/main/docs/README.md#strategy
318
- [documentation-errors]: https://github.com/panva/node-openid-client/blob/main/docs/README.md#errors
319
- [documentation-generators]: https://github.com/panva/node-openid-client/blob/main/docs/README.md#generators
320
- [documentation-methods]: https://github.com/panva/node-openid-client/blob/main/docs/README.md#client-authentication-methods
321
- [documentation-webfinger]: https://github.com/panva/node-openid-client/blob/main/docs/README.md#issuerwebfingerinput
322
- [express-openid-connect]: https://www.npmjs.com/package/express-openid-connect
323
- [oauth4webapi]: https://github.com/panva/oauth4webapi#readme
226
+ [^cjs]: CJS style `require('openid-client')` is possible in Node.js versions where `process.features.require_module` is `true` or with the `--experimental-require-module` Node.js CLI flag.