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_id and client_secret are sent in the Authorization header
  • 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_id and client_secret sent 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_secret using HMAC algorithm (HS256, HS384, HS512)
  • JWT includes standard claims: iss, sub, aud, jti, exp, iat
  • Sent as client_assertion parameter with client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer
  • More secure - secret never sent directly
  • Provides replay protection via jti (JWT ID) and exp (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_uri or jwks during 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_secret issued 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

MethodSecurity LevelShared SecretUse Case
private_key_jwtHighestNoConfidential clients, high security
tls_client_authHighestNoEnterprise, mutual TLS infrastructure
client_secret_jwtHighYesConfidential clients, standard security
client_secret_basicMediumYesConfidential clients, backward compatibility
client_secret_postLow-MediumYesLegacy systems only
noneRequires PKCENoPublic clients (SPAs, mobile apps)

Recommendations

For Confidential Clients

Priority order:

  1. private_key_jwt - Best security, no shared secret
  2. client_secret_jwt - Good security with shared secret
  3. client_secret_basic - Acceptable for compatibility
  4. client_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_jwt with strong key management
  • tls_client_auth if 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": []
}

References