Bug Description
When registering an SSO OIDC provider via register-sso-provider.ts, the tokenEndpointAuthentication field is optional with no default value. When unset, better-auth's SSO plugin (index.mjs:595) defaults to client_secret_basic:
authentication: config.tokenEndpointAuthentication === "client_secret_post" ? "post" : "basic"
In client_secret_basic mode, better-auth encodes credentials as Base64(client_id:client_secret) without URL-encoding the values first, as required by RFC 6749 §2.3.1.
This causes OIDC providers to decode + as a space, = as a delimiter, etc., resulting in a secret mismatch and invalid_client error.
Steps to Reproduce
- Register an SSO OIDC provider using
register-sso-provider.ts without setting tokenEndpointAuthentication
- Use a client secret that contains
+, =, /, or other Base64 special characters
- Attempt SSO login
- Token exchange fails with
invalid_client
Expected Behavior
Token exchange should succeed regardless of special characters in the client secret.
Root Cause
register-sso-provider.ts passes tokenEndpointAuthentication as-is (undefined when not set)
undefined === "client_secret_post" evaluates to false, so better-auth uses "basic"
- better-auth does not URL-encode credentials before Base64 encoding in
client_secret_basic mode (violates RFC 6749 §2.3.1)
Proposed Fix
Default tokenEndpointAuthentication to 'client_secret_post' in register-sso-provider.ts to avoid the upstream encoding issue:
tokenEndpointAuthentication:
ssoConfig.oidcConfig.tokenEndpointAuthentication || 'client_secret_post',
This is a workaround — the root cause is in better-auth's SSO plugin, which should URL-encode credentials per RFC 6749 §2.3.1 when using client_secret_basic.
Environment
- Sim version: v0.5.113 (main branch)
- better-auth: 1.3.12
- Affected file:
packages/db/scripts/register-sso-provider.ts