OAuth 2.0 client authentication
The Connect2id server supports all standard methods for authenticating clients at the token endpoint, specified in the core OAuth 2.0 spec and various extensions. Each method has its own security properties. This guide will help you choose the most appropriate one for your client application. But first some basics.
1. Confidential vs public OAuth 2.0 clients
Confidential clients are those that have the capability to store secrets which cannot be accessed by the end-user or other parties. Traditional web applications with a backend server fall into this category.
Public clients on the other hand do not have this capability, so they cannot be reasonably authenticated at the token endpoint. Examples are native applications running on a user’s device or computer, and browser based (JavaScript) applications.
The two client types are defined in the OAuth 2.0 framework spec (RFC 6749).
2. Why authenticate OAuth 2.0 clients?
Client authentication ensures the tokens get issued to a legitimate client and not some other, potentially malicious, party.
Public clients, which don’t get authenticated, may for this reason only get issued with tokens that have a restricted scope.
3. The two types of client credential
The credential a client uses to authenticate falls into one of these two types:
-
Shared secret – The Connect2id server issues the client with a secret (password) that is stored by the server as well as the client.
-
Private key – The client generates a private RSA or EC key and stores it securely. The client then authenticates by signing an assertion (a JWT) with the private key, or by using the private key in a client X.509 certificate based authentication during the TLS handshake of the HTTPS connection.
4. Private key based authentication is more secure
Of the two methods the one based on a private key has stronger security properties.
-
A client can store the private key in a Hardware Security Module (HSM) or a Trusted Platform Module (TPM) where the signing is performed internally, within the module, and extraction of the stored keys is not possible. This can reduce the risk of client impersonation significantly.
-
The authorisation server doesn’t keep any client-related credentials, limiting potential exposure.
-
The signed assertions (JWT) expire, limiting the time window for replay if they get accidentally leaked. Client certificates can also be made to expire quickly.
-
Finally, the issued tokens can be bound to the private key, enabling resource servers to require the client to prove its key possession when the token is submitted, thus upgrading the security of the OAuth 2.0 bearer tokens.
5. Supported client authentication methods
The Connect2id server supports the following standard methods for client authentication. Use their designations when you register a client to set the preferred method.
For an up-to-date list of the supported client authentication methods check the Connect2id server datasheet.
5.1 Shared secret based
5.1.1 client_secret_basic
This is essentially basic authentication,
tweaked for OAuth 2.0 by applying additional application/x-www-form-urlencoded
encoding to the client_id and client_secret. This is the simplest but also
the least secure method.
The Connect2id server will automatically generate a secret for the client during registration. To let the client determine the secret use the custom preferred_client_secret registration parameter.
The client authentication is passed in the Authorization HTTP header.
POST /token HTTP/1.1
Host: c2id.com
Content-Type: application/x-www-form-urlencoded
Authorization: Basic czZCaGRSa3F0Mzo3RmpmcDBaQnIxS3REUmJuZlZkbUl3
grant_type=authorization_code
&code=n0esc3NRze7LTCu7iYzS6a5acc3f0ogp4
&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
5.1.2 client_secret_post
Differs from client_secret_basic in that the credentials are passed in the request body as form parameters.
POST /token HTTP/1.1
Host: c2id.com
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code
&code=n0esc3NRze7LTCu7iYzS6a5acc3f0ogp4
&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
&client_id=s6BhdRkqt3
&client_secret=7Fjfp0ZBr1KtDRbnfVdmIw
5.1.3 client_secret_jwt
Also uses a client secret, but this time the secret is used as a key to compute a hash-based message authentication code (HMAC) for a JWT assertion. Has stronger security properties than client_secret_basic and client_secret_post because the secret itself doesn’t get transmitted to the server, reducing the damage if the token request gets accidentally sent over plain HTTP. The JWT expiration limits the time window for replay.
The JWT header must include the alg parameter to specify the HMAC algorithm. Other header parameters are not required.
Example JWT header:
{
"alg" : "HS256"
}
The JWT contains the following claims:
- iss and sub set to the
client_id. - aud set to the issuer URL of the Connect2id server, or to the endpoint URL where the client intends to authenticate, such as the token endpoint URL. When strict audience checking is configured only the issuer URL is accepted.
- exp set the JWT expiration time.
- jti set to a unique identifier for the JWT, used to prevent replay (optional).
- nbf set to time before which the JWT must not be accepted for processing (optional).
- iat set to the JWT issue time (optional).
Example JWT claims:
{
"iss" : "oe7aiz60",
"sub" : "oe7aiz60",
"aud" : "https://demo.c2id.com",
"exp" : 1453021544,
"jti" : "Eefaevo0"
}
The client authenticates with client_secret_jwt by including the
client_assertion_type parameter set to
urn:ietf:params:oauth:client-assertion-type:jwt-bearer and the
client_assertion parameter set to the serialised JWT.
POST /token HTTP/1.1
Host: c2id.com
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code
&code=n0esc3NRze7LTCu7iYzS6a5acc3f0ogp4
&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer
&client_assertion=eyJhbGciOiJSUzI1NiIsImtpZCI6IjIyIn0.eyJpc3Mi...
The Connect2id server will prevent replay of authentication JWTs that include a
jti claim, unless this security feature is
disabled.
The Connect2id server supports the standard HS256, HS384 and HS512 JWS
algorithms for JWTs secured with HMAC.
When registering for client_secret_jwt the
preferred JWS algorithm should be set.
The client_secret_jwt method is specified in OpenID Connect Core 1.0,
section 9
and in RFC 7523, section 2.2.
5.2 Private key based
5.2.1 private_key_jwt
Based on a private RSA or EC key belonging to the client to sign a JWT assertion. The matching public key must be registered in JSON Web Key (JWK) format with the Connect2id server, either by value or by URL. The registration by URL enables key-rollover without the need to update the client registration.
Starting with Connect2id server 12.12 a client can also use a qualified X.509 certificate included in the JWT header (as x5c parameter) to pass its public key. In this case registration of the client JWK set is skipped.
The JWT header must include the alg parameter to specify the signing algorithm. If the signing key was registered with a key ID (kid) it should be included as well, so the server can select the correct key in case multiple signing keys were saved in the set for rollover purposes (otherwise the server will need to check the signature with each found key).
Example JWT header:
{
"alg" : "RS256",
"kid" : "1"
}
If the client is using a qualified certificate it must be included in the “x5c” header parameter (or the entire certificate chain if intermediate authorities exist).
{
"alg" : "RS256",
"x5c" : [ "MIIE3jCCA8agAwIBAgICAwEwDQYJKoZIhvcNAQEFBQAwYzELMAkGA1UEBhMC..." ]
}
The JWT contains the following claims:
- iss and sub set to the
client_id. - aud set to the issuer URL of the Connect2id server, or to the endpoint URL where the client intends to authenticate, such as the token endpoint URL. When strict audience checking is configured only the issuer URL is accepted.
- exp set the JWT expiration time.
- jti set to a unique identifier for the JWT, used to prevent replay (optional).
- nbf set to time before which the JWT must not be accepted for processing (optional).
- iat set to the JWT issue time (optional).
Example JWT claims:
{
"iss" : "oe7aiz60",
"sub" : "oe7aiz60",
"aud" : "https://demo.c2id.com",
"exp" : 1453021544,
"jti" : "Eefaevo0"
}
The client authenticates with private_key_jwt by including the
client_assertion_type parameter set to
urn:ietf:params:oauth:client-assertion-type:jwt-bearer and the
client_assertion parameter set to the serialised JWT.
POST /token HTTP/1.1
Host: c2id.com
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code
&code=n0esc3NRze7LTCu7iYzS6a5acc3f0ogp4
&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer
&client_assertion=eyJhbGciOiJSUzI1NiIsImtpZCI6IjIyIn0.eyJpc3Mi...
The Connect2id server will prevent replay of authentication JWTs that include a
jti claim, unless this security feature is
disabled.
The Connect2id server supports RSA and EC keys:
-
Use the
RS256,RS384,RS512,PS256,PS384orPS512JWS algorithm to sign the JWT assertion with a private RSA key (minimum required key length is 2048 bits). -
Use
ES256,ES384orES512JWS algorithm to sign the JWT assertion with a private EC key (requires matching curve).
When registering for private_key_jwt the
preferred JWS algorithm should be set.
The private_key_jwt method is specified in OpenID Connect Core 1.0,
section 9
and in RFC 7523, section 2.2.
5.2.2 tls_client_auth
The client authenticates with an X.509 certificate submitted to the Connect2id server during the TLS handshake. The client certificate must be issued by a trusted Certificate Authority (CA) and will typically be validated by a dedicated TLS termination proxy in front of the server.
When registering for tls_client_auth the expected
subject DN of the certificate must be set.
Note, the client must include its client_id in the HTTP request body to
identify itself.
POST /token HTTP/1.1
Host: c2id.com
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code
&code=n0esc3NRze7LTCu7iYzS6a5acc3f0ogp4
&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
&client_id=s6BhdRkqt3
A benefit of this method is that the issued access token is bound to the client certificate, which fixes the bearer weakness of regular OAuth 2.0 access tokens. This client authentication method and the binding are specified in the mTLS OAuth 2.0 extension (RFC 8705).
5.2.3 self_signed_tls_client_auth
Similarly to the tls_client_auth method the client authenticates with a X.509 certificate submitted to the Connect2id server during the TLS handshake, but the certificate can be self-signed (self-issued) and thus no CA and X.509 based public key infrastructure (PKIX) is required. The TLS termination proxy is configured to accept self-signed certificates.
The validity of the client certificate is established by the client having its public key of the certificate registered with the Connect2id server, in JWK format by value or URL, as with private_key_jwt.
The client must include its client_id in the HTTP request body to identify
itself.
POST /token HTTP/1.1
Host: c2id.com
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code
&code=n0esc3NRze7LTCu7iYzS6a5acc3f0ogp4
&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
&client_id=s6BhdRkqt3
The issued access token will get bound to the client certificate, addressing the bearer weakness of regular OAuth 2.0 access tokens. This client authentication method and the binding are specified in the mTLS OAuth 2.0 extension (RFC 8705).
6. Limiting the accepted client authentication methods and JWS algorithms
To limit the client authentication methods accepted by a Connect2id server deployment edit the op.token.authMethods configuration setting.
For example, if your policy prohibits public OAuth 2.0 clients remove the
none method from the list.
To limit the available JWS algorithms for the JWT assertions edit the op.token.authJWSAlgs configuration setting.
The available authentication methods and algorithms can also be limited in your developer portal which manages requests to the client registration endpoint.
7. Credential update and rollover
7.1 Client secret expiration, update and rollover
Client secrets generated by the Connect2id server do not expire by default, unless the server is configured to enforce a specific secret lifetime. Once a client expires, the client will no longer be able to authenticate at the token endpoint or perform other requests that require client authentication.
Example configuration setting the client secret lifetime to 168 hours (1 week):
op.reg.clientSecretLifetime=168
To obtain a new client secret, submit a client update
request with the
refresh_client_secret metadata
field set to true, for example:
PUT /clients/s6BhdRkqt3 HTTP/1.1
Authorization: Bearer SQvs1wv1NcAgsZomWWif0d9SDO0GKHYrUN6YR0ocmN0
Content-Type: application/json
{
"client_id" : "s6BhdRkqt3",
"redirect_uris" : [ "https://client.example.org/cb" ],
"client_name" : "My App",
"refresh_client_secret" : true
}
If the existing secret has already expired, or the Connect2id server is configured to always refresh the secret on client update (the default setting), the refresh_client_secret field can be omitted.
After a secret refresh, the previous secret remains valid for 30 minutes, allowing the client application to switch to the new secret without experiencing authentication failures during the rollover period.
7.2 Private key update and rollover
Clients that authenticate using private keys determine their own expiration and rotation policies.
To perform a seamless rollover, the client should add the new singing key to
its existing public JWK (either registered by value with jwks or by URL with
jwks_uri) and then begin using the new key for authentication. The Connect2id
server will automatically detect and accept the new key.
8. Authentication method migration
The Connect2id server supports seamless migration of a client’s authentication method, allowing a client to switch from one authentication method to another without interrupting ongoing operations.
This capability is useful when upgrading security posture, for example when
migrating from a shared-secret method such as client_secret_basic to an
asymmetric method such as private_key_jwt.
The migration proceeds as follows:
-
Dual authentication phase – The client begins including both the current and the future authentication methods in its requests.
-
Registration update – The client registration is updated to set the new authentication method as the configured
token_endpoint_auth_method. -
Completion – After the registration change takes effect, the client continues sending only the new authentication method.
This approach ensures uninterrupted client operation while the registration update propagates and avoids authentication failures during the transition period.
The dual-authentication mechanism is supported for the following endpoints:
- Token endpoint
- Token introspection endpoint
- Token revocation endpoint
- Pushed authorization request (PAR) endpoint
Example token request with dual client authentication – client_secret_basic
and private_key_jwt:
POST /token HTTP/1.1
Host: c2id.com
Content-Type: application/x-www-form-urlencoded
Authorization: Basic czZCaGRSa3F0Mzo3RmpmcDBaQnIxS3REUmJuZlZkbUl3
grant_type=authorization_code
&code=n0esc3NRze7LTCu7iYzS6a5acc3f0ogp4
&redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer
&client_assertion=eyJhbGciOiJSUzI1NiIsImtpZCI6IjEifQ.eyJpc3MiOiJzNkJoZFJrcXQzIi
c3ViIjoiczZCaGRSa3F0MyIsImF1ZCI6Imh0dHBzOi8vc2VydmVyLmV4YW1wbGUuY29tL3Rva2VuIiw
ianRpIjoiN2Y5ZmE0NjUtYjVjYi00YjA4LWE4MjQtYzJhNzY1NDA2YmU1IiwiZXhwIjoxNzEwMDAwaf
MDAwfQ.Peemeedono2dbued8mio4AhmCheeSh0vooLa
Example log message, showing the second authentication method succeeding:
INFO TOKEN - [OP6203] Bad authentication: Client not registered for the authentication method: client_id=eavk44cim5q4q method=client_secret_basic candidate_methods=[client_secret_basic,private_key_jwt] client_auth_id=0P2D6QUGSNpy_9n8
INFO TOKEN - [OP6204] Authenticated: client_id=eavk44cim5q4q method=private_key_jwt candidate_methods=[client_secret_basic,private_key_jwt] client_auth_id=0P2D6QUGSNpy_9n8
8. How to debug client authentication errors
Clients that fail to authenticate at a Connect2id server endpoint, such as the token endpoint, will receive an HTTP 401 Unauthorized error response.
The error_description will have a helpful checklist of all possible causes why the client authentication may have failed. The actual cause will not be disclosed in the HTTP response, for security reasons.
HTTP/1.1 401 Unauthorized
Content-Type: application/json
{
"error" : "invalid_client",
"error_description" : "Invalid client: Possible causes may be missing /
invalid client_id, missing client authentication,
invalid or expired client secret, invalid or expired
JWT authentication, invalid or expired client X.509
certificate, or an unexpected client authentication
method",
"client_auth_id" : "cgXB4EyYViWPt6g2"
}
If you have access to the server logs, or the client account is provisioned with access to its authentication events, the unique client_auth_id in the error response can be used to quickly locate the particular authentication and obtain the recorded cause.
Example error log message:
2022-06-03T12:21:48,974 INFO http-nio-8080-exec-26 TOKEN - [OP6203] Bad client
authentication: Client certificate subject DN doesn't match: Expected
CN=app923412, received CN=app912430: client_id=pjbizwoy5mjei
method=tls_client_auth client_auth_id=cgXB4EyYViWPt6g2
9. Client authentication events
The Connect2id server includes a plugin interface for intercepting all client authentications - both successful and failed, with additional context, such as the unique client_auth_id explained above to identify the authentication event.
This interface can be used to implement special client authentication auditing and reporting, or a self-service panel where client developers can go to quickly debug HTTP 401 Unauthorized errors.
10. Developer resources
The OAuth 2.0 / OpenID Connect SDK for Java that Connect2id maintains provides support for all standard client authentication methods.