Client authentication
Note that client authentication can be used both in the context of end-user authentication (for example in combination with Authorization Code Flow), and as a system-only authentication using Client Credentials only.
The type of client authentication method available will depend on the Security Domains , context and application.
As described in the OIDC specification, clients can be Confidential Clients, capable of keeping secrets or Public Clients not capable of holding secrets (or some other factor deeming client secrets unnecessary).
Client identifier
In any case, a Client Id (Client Identifier) is required. This means that, regardless of Confidential or Public clients, a Client Id must be registered with (and possibly issued by) Buypass OpenID Provider before use.
The Client Id will be registered within a Security Domain and will also need to specify and handle scopes and claims relevant for that domain.
Tokens will not be issued to unregistered clients.
Client authentication methods
In general, Buypass only support Confidential Clients. The exception is clients using the Implicit Flow. All other supported flows and grants require Confidential Clients.
OIDC define several client authentication methods for Confidential Clients: Client Authentication.
client_secret_basic / client_secret_post
These authentication methods are only supported in Security Domains where the security risk of client impersonation is low or in closed domains where the additional security is considered unnessesary.
private_key_jwt
Buypass uses private_key_jwt as a default client authentication mechanism for open Security Domains and high level IDs like the BuypassID Domain.
In short this means that in addition to the Client Id, a public key must be registered with (and possibly issued by) Buypass. The corresponding private key must be used by the client to sign a JSON Web Token (JWT) sent as part of the client authentication request. This is typically done using a Buypass Merchant certificate or a more general Enterprise certificate, depending on the application.
Client request JWT claims
The following minimum claims must be defined in the client request JWT:
Claim | Required | Description | Example value |
---|---|---|---|
iss | yes | Issuer. Should be set to the Client Id (Client Identifier) of the OIDC/OAuth2 client | oidc-client |
sub | yes | Subject. Should be set to the Client Id (Client Identifier) of the OIDC/OAuth2 client | oidc-client |
aud | yes | Audience. Should be set to the URL of the OpenID Provider/OAuth2 Authorization Server issuer URL. | https://auth.buypass.no/auth/realms/SECURITYDOMAIN |
jti | yes | JWT ID. A unique identifier for the token, which can be used to prevent reuse of the token. These tokens MUST only be used once. Se also: JWT ID Claim | 461d5788-2a18-4e63-9e35-7097e02b0227 |
exp | yes | Expiration time on or after which the JWT MUST NOT be accepted for processing. See also: Expiration Time Claim Date format should be in "NumericDate", ref JWT terminology. | 1510831578 |
iat | yes | Time at which the JWT was issued. See also: Issued At Claim Date format should be in "NumericDate", ref JWT terminology. | 1510831518 |
Example
Example below using a small NPM cmdline tool for generating the JWT: jwtgen. Using the curl tool, the JWT is then sent as authentication data in the post request directly to the token endpoint.
SD="SECURITYDOMAIN" ISSUER_URL="https://auth.buypass.no/auth/realms/${SD}"; TOKEN_URL="${ISSUER_URL}/protocol/openid-connect/token"; CLIENT_ID="oidc-client"; # Assuming private key and certificate is available in the keystore named: # ${CLIENT_ID}-keystore.p12 # Export the certificate openssl pkcs12 -in ${CLIENT_ID}-keystore.p12 -nokeys -out ${CLIENT_ID}-jwt-cert.pem # Export the private key (unencrypted) openssl pkcs12 -in ${CLIENT_ID}-keystore.p12 -nodes -nocerts -out ${CLIENT_ID}-jwt-key.pem JTI=`uuidgen` JSON="{ \"iss\": \"${CLIENT_ID}\", \"sub\": \"${CLIENT_ID}\", \"aud\": \"${ISSUER_URL}\", \"jti\": \"${JTI}\" }" # Generate signed JWT (including exp and iat claims) CLIENT_JWT=`jwtgen -a RS256 -e 3600 -p ${CLIENT_ID}-jwt-key.pem --claims "${JSON}"` # Post client authorization request using curl curl -i -w "\n" \ -H "Content-Type: application/x-www-form-urlencoded" \ -X POST "${TOKEN_URL}" \ -d "grant_type=client_credentials"\ "&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer"\ "&client_assertion=${CLIENT_JWT}"
Two-Way TLS client authentication
In addition to supporting the standard OIDC client authentication methods, Buypass also support two-way TLS or Mutual TLS authentication (mTLS), https://tools.ietf.org/html/rfc5246#section-7.4.6.
Note that this authentication method is only available for selected clients and authentication scenarios for B2B setups (for example in the EnterpriseID Domain).
The two-way TLS authentication protocol is standardised and done as a part of the low level TLS socket connection and transparent to the HTTP and OIDC/OAuth protocols. The protocol uses certificates and the Client Id must somehow be communicated in the certificate. This is one of the reasons that the applications of Two-way TLS is service/application limited, as there need to be a correlation between the certificate metadata and the OIDC client.
Example
Using the curl tool, the two-way TLS authentication is done using the supplied certificate (and client key). The further client authentication is then further implicit as the request is done over the established TLS connection, directly to the token endpoint.
Note the parameter "?_tlsclientauth=1" added to the TOKEN_URL. The parameter is used to trigger two-way TLS only if requested, if multiple authentication methods are available.
SD="SECURITYDOMAIN" ISSUER_URL="https://auth.buypass.no/auth/realms/${SD}"; # Note: Parameter to trigger MTLS inly when requested TOKEN_URL="${ISSUER_URL}/protocol/openid-connect/token?_tlsclientauth=1"; CLIENT_ID="oidc-client"; # Assuming private key and certificate is available in the keystore named: # ${CLIENT_ID}-keystore.p12 # Export the certificate openssl pkcs12 -in ${CLIENT_ID}-keystore.p12 -nokeys -out ${CLIENT_ID}-cert.pem # Export the private key (unencrypted) openssl pkcs12 -in ${CLIENT_ID}-keystore.p12 -nodes -nocerts -out ${CLIENT_ID}-key.pem # Post client authorization request using curl curl -v -i -w "\n" \ --cert ${CLIENT_ID}-cert.pem \ --key ${CLIENT_ID}-key.pem \ -H "Content-Type: application/x-www-form-urlencoded" \ -X POST "${TOKEN_URL}" \ -d "grant_type=client_credentials"\ "&client_id=${CLIENT_ID}"