You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs: clarify PKCE vs client authentication and refresh handling
Documents the conclusions from the PKCE/refresh standards review so the
recurring confusion doesn't return:
- guide/pkce.md: new section explaining that code_verifier applies only to
the authorization_code exchange (never refresh), that PKCE is not a
substitute for client_secret, and how to allow public clients to refresh
without a secret.
- Model#getClient JSDoc: clientSecret is absent for public clients and for
PKCE authorization_code requests even when the client has a secret, so the
model must reject a confidential client that omits it.
- requireClientAuthentication (server.js JSDoc + index.d.ts): disabling a
grant turns off the client_secret presence check for the whole grant (all
clients), so per-client enforcement belongs in getClient.
Regenerated docs/api/model.md and docs/api/server.md.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: docs/api/model.md
+8Lines changed: 8 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -84,6 +84,14 @@ This model function is **required** for all grant types.
84
84
-`refresh_token` grant
85
85
-`password` grant
86
86
87
+
**Remarks:**
88
+
`clientSecret` is `null`/absent for public clients, and also for
89
+
`authorization_code` requests that authenticate with PKCE (a `code_verifier`)
90
+
instead of a secret — even if the client *has* a `client_secret`. PKCE is
91
+
**not** a substitute for client authentication: your implementation must
92
+
reject (return a falsy value) a confidential client that should have
93
+
presented its `client_secret` but did not.
94
+
87
95
**Kind**: instance method of [<code>Model</code>](#Model)
88
96
**Fulfil**: [<code>ClientData</code>](#ClientData) - An `Object` representing the client and associated data, or a falsy value if no such client could be found.
Copy file name to clipboardExpand all lines: docs/api/server.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -158,7 +158,7 @@ function authorizeHandler(options) {
158
158
Retrieves a new token for an authorized token request.
159
159
**Remarks:**
160
160
If `options.allowExtendedTokenAttributes` is `true` any additional properties set on the object returned from `Model#saveToken() <Model#saveToken>` are copied to the token response sent to the client.
161
-
By default, all grant types require the client to send it's `client_secret` with the token request. `options.requireClientAuthentication` can be used to disable this check for selected grants. If used, this server option must be an object containing properties set to `true` or `false`. Possible keys for the object include all supported values for the token request's `grant_type` field (`authorization_code`, `client_credentials`, `password` and `refresh_token`). Grants that are not specified default to `true` which enables verification of the `client_secret`.
161
+
By default, all grant types require the client to send it's `client_secret` with the token request. `options.requireClientAuthentication` can be used to disable this check for selected grants. If used, this server option must be an object containing properties set to `true` or `false`. Possible keys for the object include all supported values for the token request's `grant_type` field (`authorization_code`, `client_credentials`, `password` and `refresh_token`). Grants that are not specified default to `true` which enables verification of the `client_secret`. Note: setting a grant to `false` disables only the *presence* check of the `client_secret` for that grant, and does so for **all** clients (not just public ones); it does not validate a secret that is sent. The same applies to `authorization_code` requests that use PKCE (a `code_verifier`), where the presence check is skipped. Per-client (public vs confidential) authentication must therefore be enforced in your `Model#getClient() <Model#getClient>` implementation, which should reject a confidential client that fails to present its `client_secret`.
Copy file name to clipboardExpand all lines: lib/server.js
+1-1Lines changed: 1 addition & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -183,7 +183,7 @@ class OAuth2Server {
183
183
* Retrieves a new token for an authorized token request.
184
184
* **Remarks:**
185
185
* If `options.allowExtendedTokenAttributes` is `true` any additional properties set on the object returned from `Model#saveToken() <Model#saveToken>` are copied to the token response sent to the client.
186
-
* By default, all grant types require the client to send it's `client_secret` with the token request. `options.requireClientAuthentication` can be used to disable this check for selected grants. If used, this server option must be an object containing properties set to `true` or `false`. Possible keys for the object include all supported values for the token request's `grant_type` field (`authorization_code`, `client_credentials`, `password` and `refresh_token`). Grants that are not specified default to `true` which enables verification of the `client_secret`.
186
+
* By default, all grant types require the client to send it's `client_secret` with the token request. `options.requireClientAuthentication` can be used to disable this check for selected grants. If used, this server option must be an object containing properties set to `true` or `false`. Possible keys for the object include all supported values for the token request's `grant_type` field (`authorization_code`, `client_credentials`, `password` and `refresh_token`). Grants that are not specified default to `true` which enables verification of the `client_secret`. Note: setting a grant to `false` disables only the *presence* check of the `client_secret` for that grant, and does so for **all** clients (not just public ones); it does not validate a secret that is sent. The same applies to `authorization_code` requests that use PKCE (a `code_verifier`), where the presence check is skipped. Per-client (public vs confidential) authentication must therefore be enforced in your `Model#getClient() <Model#getClient>` implementation, which should reject a confidential client that fails to present its `client_secret`.
0 commit comments