Token Endpoint Authentication Methods
The token_endpoint_auth_method attribute specifies how the client authenticates when requesting tokens from the token endpoint.
Standard Methods
client_secret_basic
Most common method for confidential clients
- Client authenticates using HTTP Basic Authentication
client_idandclient_secretare sent in theAuthorizationheader- Format:
Authorization: Basic base64(client_id:client_secret) - Widely supported and straightforward to implement
Example:
POST /token HTTP/1.1
Host: authorization-server.com
Authorization: Basic czZCaGRSa3F0Mzo3RmpmcDBaQnIxS3REUmJuZlZkbUl3
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA
client_secret_post
Client credentials in POST body
client_idandclient_secretsent as form parameters in request body- Less secure than Basic Auth since credentials appear in request body
- May be logged more easily by proxies and web servers
- Use only when Basic Auth is not supported
Example:
POST /token HTTP/1.1
Host: authorization-server.com
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA
&client_id=s6BhdRkqt3&client_secret=7Fjfp0ZBr1KtDRbnfVdmIw
client_secret_jwt
JWT signed with shared secret
- Client creates a JWT signed with the
client_secretusing HMAC algorithm (HS256, HS384, HS512) - JWT includes standard claims:
iss,sub,aud,jti,exp,iat - Sent as
client_assertionparameter withclient_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer - More secure - secret never sent directly
- Provides replay protection via
jti(JWT ID) andexp(expiration)
Example:
POST /token HTTP/1.1
Host: authorization-server.com
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA
&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer
&client_assertion=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
JWT Claims:
{
"iss": "s6BhdRkqt3",
"sub": "s6BhdRkqt3",
"aud": "https://authorization-server.com/token",
"jti": "unique-jwt-id-12345",
"exp": 1516239722,
"iat": 1516239022
}
private_key_jwt
JWT signed with private key (recommended)
- Client creates a JWT signed with its private key using asymmetric algorithm (RS256, ES256, PS256, etc.)
- Public key registered via
jwks_uriorjwksduring client registration - Most secure method - no shared secret to compromise
- Same JWT structure as
client_secret_jwt - Preferred for high-security applications
Registration includes:
{
"token_endpoint_auth_method": "private_key_jwt",
"jwks_uri": "https://client.example.com/.well-known/jwks.json"
}
Example:
POST /token HTTP/1.1
Host: authorization-server.com
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA
&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer
&client_assertion=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
none
No authentication (public clients)
- Used for applications that cannot securely store credentials
- Typical use cases:
- Single Page Applications (SPAs)
- Mobile applications
- Native applications
- Desktop applications
- MUST use PKCE (Proof Key for Code Exchange) for security
- No
client_secretissued during registration
Example:
POST /token HTTP/1.1
Host: authorization-server.com
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA
&client_id=s6BhdRkqt3
&code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
Extended Methods (RFC 8705 - OAuth 2.0 Mutual-TLS)
tls_client_auth
Mutual TLS with CA-signed certificates
- Client certificate presented during TLS handshake
- Certificate must be signed by trusted CA
- Certificate subject DN must match registered value
- Authorization server validates certificate chain
- Very high security for enterprise scenarios
self_signed_tls_client_auth
Mutual TLS with self-signed certificates
- Client presents self-signed certificate during TLS handshake
- Public key or certificate registered during client registration
- More flexible than CA-signed certificates
- Provider validates against registered certificate/key
Security Comparison
| Method | Security Level | Shared Secret | Use Case |
|---|---|---|---|
private_key_jwt | Highest | No | Confidential clients, high security |
tls_client_auth | Highest | No | Enterprise, mutual TLS infrastructure |
client_secret_jwt | High | Yes | Confidential clients, standard security |
client_secret_basic | Medium | Yes | Confidential clients, backward compatibility |
client_secret_post | Low-Medium | Yes | Legacy systems only |
none | Requires PKCE | No | Public clients (SPAs, mobile apps) |
Recommendations
For Confidential Clients
Priority order:
private_key_jwt- Best security, no shared secretclient_secret_jwt- Good security with shared secretclient_secret_basic- Acceptable for compatibilityclient_secret_post- Avoid if possible
For Public Clients
none- ONLY option for public clients- MUST use PKCE to prevent authorization code interception
- Never use shared secrets in public clients (can be extracted)
For Enterprise/High Security
private_key_jwtwith strong key managementtls_client_authif mutual TLS infrastructure exists- Rotate keys regularly
- Use hardware security modules (HSM) for key storage
Example Registrations
Confidential Web Application
{
"client_name": "My Web App",
"token_endpoint_auth_method": "private_key_jwt",
"jwks_uri": "https://example.com/.well-known/jwks.json",
"grant_types": ["authorization_code", "refresh_token"],
"response_types": ["code"]
}
Single Page Application
{
"client_name": "My SPA",
"token_endpoint_auth_method": "none",
"grant_types": ["authorization_code", "refresh_token"],
"response_types": ["code"]
}
Backend Service
{
"client_name": "My Service",
"token_endpoint_auth_method": "private_key_jwt",
"jwks_uri": "https://service.example.com/.well-known/jwks.json",
"grant_types": ["client_credentials"],
"response_types": []
}