Skip to content

Commit 7c963cb

Browse files
minijeong-logemir-karabeg
authored andcommitted
fix(sso): default tokenEndpointAuthentication to client_secret_post (#3627)
* fix(sso): default tokenEndpointAuthentication to client_secret_post better-auth's SSO plugin does not URL-encode credentials before Base64 encoding in client_secret_basic mode (RFC 6749 §2.3.1). When the client secret contains special characters (+, =, /), OIDC providers decode them incorrectly, causing invalid_client errors. Default to client_secret_post when tokenEndpointAuthentication is not explicitly set to avoid this upstream encoding issue. Fixes #3626 * fix(sso): use nullish coalescing and add env var for tokenEndpointAuthentication - Use ?? instead of || for semantic correctness - Add SSO_OIDC_TOKEN_ENDPOINT_AUTH env var so users can explicitly set client_secret_basic when their provider requires it * docs(sso): add SSO_OIDC_TOKEN_ENDPOINT_AUTH to script usage comment Signed-off-by: Mini Jeong <mini.jeong@navercorp.com> * fix(sso): validate SSO_OIDC_TOKEN_ENDPOINT_AUTH env var value Replace unsafe `as` type cast with runtime validation to ensure only 'client_secret_post' or 'client_secret_basic' are accepted. Invalid values (typos, empty strings) now fall back to undefined, letting the downstream ?? fallback apply correctly. Signed-off-by: Mini Jeong <mini.jeong@navercorp.com> --------- Signed-off-by: Mini Jeong <mini.jeong@navercorp.com>
1 parent bccbf5a commit 7c963cb

File tree

1 file changed

+11
-1
lines changed

1 file changed

+11
-1
lines changed

packages/db/scripts/register-sso-provider.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
* SSO_OIDC_CLIENT_ID=your_client_id
2222
* SSO_OIDC_CLIENT_SECRET=your_client_secret
2323
* SSO_OIDC_SCOPES=openid,profile,email (optional)
24+
* SSO_OIDC_TOKEN_ENDPOINT_AUTH=client_secret_post|client_secret_basic (optional, defaults to client_secret_post)
2425
*
2526
* SAML Providers:
2627
* SSO_SAML_ENTRY_POINT=https://your-idp/sso
@@ -215,6 +216,11 @@ function buildSSOConfigFromEnv(): SSOProviderConfig | null {
215216
pkce: process.env.SSO_OIDC_PKCE !== 'false',
216217
authorizationEndpoint: process.env.SSO_OIDC_AUTHORIZATION_ENDPOINT,
217218
tokenEndpoint: process.env.SSO_OIDC_TOKEN_ENDPOINT,
219+
tokenEndpointAuthentication:
220+
process.env.SSO_OIDC_TOKEN_ENDPOINT_AUTH === 'client_secret_post' ||
221+
process.env.SSO_OIDC_TOKEN_ENDPOINT_AUTH === 'client_secret_basic'
222+
? process.env.SSO_OIDC_TOKEN_ENDPOINT_AUTH
223+
: undefined,
218224
userInfoEndpoint: process.env.SSO_OIDC_USERINFO_ENDPOINT,
219225
jwksEndpoint: process.env.SSO_OIDC_JWKS_ENDPOINT,
220226
discoveryEndpoint:
@@ -507,7 +513,11 @@ async function registerSSOProvider(): Promise<boolean> {
507513
clientSecret: ssoConfig.oidcConfig.clientSecret,
508514
authorizationEndpoint: ssoConfig.oidcConfig.authorizationEndpoint,
509515
tokenEndpoint: ssoConfig.oidcConfig.tokenEndpoint,
510-
tokenEndpointAuthentication: ssoConfig.oidcConfig.tokenEndpointAuthentication,
516+
// Default to client_secret_post: better-auth sends client_secret_basic
517+
// credentials without URL-encoding per RFC 6749 §2.3.1, so '+' in secrets
518+
// is decoded as space by OIDC providers, causing invalid_client errors.
519+
tokenEndpointAuthentication:
520+
ssoConfig.oidcConfig.tokenEndpointAuthentication ?? 'client_secret_post',
511521
jwksEndpoint: ssoConfig.oidcConfig.jwksEndpoint,
512522
pkce: ssoConfig.oidcConfig.pkce,
513523
discoveryEndpoint:

0 commit comments

Comments
 (0)