Token Endpoint

Exchanging Grants for Tokens

In exchange for an OAuth 2.0 grant, clients obtain tokens (identity, access or refresh) at the token endpoint.

The token endpoint of the HID Authentication Service server accepts the following grant types:

  • Proprietary grant types:

    • Client secret PKI (urn:hid:oauth:grant-type:client-secret-pki) – the client authenticates itself via a mutual TLS (mTLS) authentication connection to the token endpoint with the client certificate which is registered as a HID Authentication Service PKI credential during registration.

    • OTP via API (api_otp) - get an OTP (returned in the response) that you can then send to a user

    • CIBA delete request (ciba_delete) - to delete a pending push request

Copy

The endpoint is exposed at the following URL (and can be obtained from the server discovery endpoint):

https://[base-server-url]/{tenant}/authn/token [POST]
Method Details
POST

Token Request

Clients must authenticate to the server with their client_id and client_secret credentials obtained at registration in order to make a token request. The default authentication method is client secret basic. However, for security reasons, it is recommended to configure a stronger authentication method, such as client secret POST, private key JWT or the HID custom authentication method client_secret_pki.

Copy

Sample token request with an authorization code grant

POST https://[base-server-url]/{tenant}/authn/token HTTP/1.1
Authorization: Bearer RTp7HwAAAW3KhwwWbFmvt2o/66OFuV7HZ52X6scd
Content-Type: application/x-www-form-urlencoded
 
grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA
&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb
Copy

Sample token request with a password grant

POST https://[base-server-url]/{tenant}/authn/token HTTP/1.1
Authorization: Bearer RTp7HwAAAW3KhwwWbFmvt2o/66OFuV7HZ52X6scd
Content-Type: application/x-www-form-urlencoded
 
grant_type=password&username=alice&password=secret
Copy

Sample token request with a client_credentials grant

POST https://[base-server-url]/{tenant}/authn/token HTTP/1.1
Authorization: Basic c3BsLWFwaTpwYXNzd29yZDAx
Content-Type: application/x-www-form-urlencoded
 
grant_type=client_credentials
Copy

Sample token request with a client_credentials grant with client credentials in the request-body (not recommended)

POST https://[base-server-url]/{tenant}/authn/token HTTP/1.1
Content-Type: application/x-www-form-urlencoded
 
grant_type=client_credentials&client_id=client1&client_secret=password01
Copy

Sample token request with a client_credentials grant using a JWT signed with client private key (recommended)

POST https://[base-server-url]/{tenant}/authn/token HTTP/1.1
Content-Type: application/x-www-form-urlencoded
 
grant_type=client_credentials&client_id=client1&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer&client_assertion=eyJhbGciOiJSUzI1NiIsImtpZCI6IjIyIn0.eyJpc3Mi[...omitted for brevity...].cC4hiUPo[...omitted for brevity...]
Note: The client must be configured to support PKI authentication and the private key used to generate the assertion must be the client’s authentication key, not the digital signature key if different.

For further information about the assertion content, go to https://tools.ietf.org/html/draft-ietf-oauth-jwt-bearer-12#section-3

Copy

Sample token request using OpenID’s ‘self_signed_tls_client_auth’ authentication method with client_credentials grant with client PKI authentication using a mTLS authentication connection to the token endpoint

POST https://[base-server-url]/{tenant}/authn/token HTTP/1.1
Content-Type: application/x-www-form-urlencoded
                 
grant_type=client_credentials&client_id=client1&scope=openid
Note: The token endpoint accepting mTLS authentication connection might be using another port, such as 8443, and the root CA certificate of client’s certificate should be stored in the HID Authentication Service truststore.
Copy

Sample token request with a HID custom grant type client_secret_pki with client authentication certificate used in a mTLS authentication connection to the token endpoint

POST https://[base-server-url]/{tenant}/authn/token HTTP/1.1
Content-Type: application/x-www-form-urlencoded
                 
grant_type=urn:hid:oauth:grant-type:client-secret-pki&client_id=client1
Copy

Sample token request with a refresh_token grant, with refresh token in the request-body

POST https://[base-server-url]/{tenant}/authn/token HTTP/1.1
Content-Type: application/x-www-form-urlencoded
 
grant_type=refresh_token&refresh_token=31701300&scope=openid%20profile%20offline_access
Copy

Sample token request with an api_otp grant using OOB authentication to get an OTP

POST https://[base-server-url]/{tenant}/authn/token HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Authorization: Bearer RTp7HwAAAV6kDLkStyOElco4/XqhuFOnqCHTypGu
 
grant_type=api_otp&username=jsmith@company.com&authType=AT_OOB
Important:
  • The request must include a device-based OOB authentication type (in this example, AT_OOB) linked to an OOB Device Type, itself linked to a valid Credential Type allowing to generate an OTP.

  • The OpenID client must have the RL_CLIENTIDM2M role which includes the FS_APIOTP permission set.

    Alternatively, you can assign the FS_APIOTP permission set to the client's existing role.

Copy

Sample request to delete a pending request

POST https://[base-server-url]/{tenant}/authn/token
Content-Type: application/json
Authorization: Bearer RTp7HwAAAV6kDLkStyOElco4/XqhuFOnqCHTypGu
grant_type=ciba_delete&auth_req_id=a95c61e0-f604-4905-98b1-26b7b87fe073   

HID Custom Token Request Parameters

Several HID custom parameters are supported to match the HID Authentication Service authentication features, although these custom parameters are all optional:

Parameter Description

device_id

For the Transaction Signing use case, this parameter is added to proceed with authentication with device.

device_externalid

For the auto-bind use case, this parameter is added.

mode

The supported authentication mode values are:

  • SYNCHRONOUS
  • ASYNCHRONOUS
  • SIGNING
  • CHALLENGE
  • SIGN_SYNCHRONOUS

By default (parameter missing), the mode is SYNCHRONOUS.

authType

Added to override the default authentication type registered to the OpenID client. This parameter is useful when the OpenID client supports multiple authentication types.

channel

Added to override the default channel registered to the OpenID client. This parameter is useful when the OpenID client has multiple authentication channels.

Note: When using the Resource owner password credentials grant type, the authType and channel custom parameters passed will be used as parameters for end user.

noToken

For the Transaction Signing, Push Authentication and RADIUS uses cases, it is necessary to authenticate without generating tokens.

In these cases, the parameter should be set to 1 to prevent the generation of a token for the OpenID client or end user.

The response will return an Access Token with a fake value (a base64-encoding of the character space ' ') as a placeholder that can be ignored:

IA==

By default, or if the parameter is missing, the value is 0 (token will be generated).

deviceCentric

For authentication with a device, set the parameter to deviceCentric=1, combined either a device_id or a device_externalid.

Possible values:

  • Integer 1 for true
  • Any other value, or missing, will be false and therefore, not deviceCentric)

client_id

Required for client authentication.

username

For end user authentication, this can be a faked value (not null, empty, or blank) as a placeholder and it will be ignored.

Token Response

See section 3.1.3.3 of the OpenID Connect Core specification

Copy

Sample response with an access and ID Token

HTTP/1.1 200 OK
Cache-Control: no-store
Pragma: no-cache
Content-Type: application/json; charset=UTF-8
 
{
    "access_token": "pxMC9gAAAW3KmzjTLKRSqLeK4Em62cucIULOX/Y3",
    "id_token": "eyJraWQiOiIxNTI5MDcwMDQ5[...truncated for brevity...] cbAqXqCCrSiYsP-Jg",
    "token_type": "Bearer",
    "expires_in": 7200
}
Note: In HID Authentication Service, access tokens are session-bound and sessions possess two timeout attributes:
  • Session inactivity timeout
  • Session timeout

The "expires_in" claim in the sample above contains the value of the second attribute - meaning the token might expire before this maximum duration, due to inactivity (it might also have been revoked, see the revoke endpoint), which is why it is strongly recommended that applications using them to use the Introspect endpoint to get of the current status of the token before use.

For further information about the tokens, see Making the most of OpenID tokens.

Copy

Sample response with an OTP returned using an api_otp grant

HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache
{
    "otp" : "2YotnFZF"
}

Retrieve the Authentication Result and Access Token

Copy

Sample request with a CIBA grant using the authentication request ID

POST https://[base-server-url]/{tenant}/authn/token HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Authorization: Bearer RTp7HwAAAXk3vsD/zWlMvdnsYBjme0uXks0qQlT0
 
grant_type=urn%3Aopenid%3Aparams%3Agrant-type%3Aciba&auth_req_id=a95c61e0-f604-4905-98b1-26b7b87fe073
Copy

Sample response with the id_token

HTTP/1.1 200 OK
Cache-Control: no-store
Pragma: no-cache
Content-Type: application/json;charset=UTF-8
Content-Length: 84
 
{
   "access_token": "rYt9pwAAAXk3wN50Qm06NLzAbv0I/XKR/zknMhIY",
   "auth_req_id": "a95c61e0-f604-4905-98b1-26b7b87fe073",
   "id_token": "eyJraWQiOiIxNjQ2OTMxNzgwNjYzIiwidHlwIjoiSldUIiwiYW..aX7OPI2IWbsC3NsniVH18rWBr2bGKlVB53gAypM2-IAoQWksnlcM9wvHp_eQefZnbqung",
   "token_type": "Bearer",
   "expires_in": 86400
}
Copy

Where the decoded id_token is:

{
    "at_hash": "A1ifydl-B1V7MqvVZUp56Q",
    "sub": "spl-cust02",
    "reason": "Reason not defined",
    "JWS": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSU....xxblIja9ZHWxaX7nMZU1h9iGEtZRtO1dhrZKq4OMNnIpRLoVzHVp1Zx2kzxdCbdjAoGHdn3OAS3wNppL5Y5nlZbZQ1inEacVjeyGZo9xYdJYwVEW3F4cIVQNRwFu0QPaBi0MPgZ7f_SPYN2IyglU9yy8MC7WylQ==",
    "PUK": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4WjK..4PQE6/w/QNUwZ21Xw9OAYWbn1pb1BopV8zhmjDQmBRpSyFIKs7iq9HOs7irQ/33KtWa3zpVHywrlELD2Lr/zIrwRFzQGWOZs6w0dAZ+OIR7igJdZQ/JhvztBL/K0pKRHlPrlQIDAQAB",
    "iss": "https://[base-server-url]/{tenant}/authn/token",
    "deviceid": 11727,
    "result": 1,
    "acr": "2",
    "urn:openid:params:jwt:claim:auth_req_id": "32709383-3542-4024-9659-43f72b803bb9",
    "auth_time": 1649789512,
    "tds_context" : "TXkgdHJhbnNhY3Rpb24gc2FtcGxlIGNvbnRleHQ=" 
    "mobile_tds_context": "TXkgbW9iaWxlIGRldmljZSB0cmFuc2FjdGlvbiBzYW1wbGUgY29udGV4dA==",
    "clientapprovalstatus": "accept",
    "exp": 1649793112,
    "iat": 1649789512
}
Copy

Sample request for RADIUS send after for push authentication

POST https://[base-server-url]/{tenant}/authn/token HTTP/1.1
Connection: close
Content-Type: application/x-www-form-urlencoded
Authorization: Bearer Uyet6AAAAYAfHAZK+t/2Qm92EL5OWcqY/PVeuaPI
 
grant_type=urn%3Aopenid%3Aparams%3Agrant-type%3Aciba&auth_req_id=32709383-3542-4024-9659-43f72b803bb9
Copy

Sample response for RADIUS send after for push authentication

HTTP/1.1 200 OK
Cache-Control: no-store
Pragma: no-cache
Content-Type: application/json;charset=UTF-8
Content-Length: 84
 
{
    "access_token": "hamx1AAAAYAfHixmK/chSkfR+sXemoONj63mPuTm",
    "auth_req_id": "32709383-3542-4024-9659-43f72b803bb9",
    "id_token": "eyJraWQiOiIxNjQ2OTMxNzgwNjYzIiwidHlwIjoiSldUIiwiYWxnIjoiUlMyNTYifQ.eyJhdF9oYXNoIjoiQTFpZnlkbC1CMVY3TXF2VlpVcDU2USIsInN1YiI6InNwbC1jdXN0MDIiLCJyZWFzb24iOiJSZWFzb24gbm90IGRlZmluZWQiLCJKV1MiOiJleUowZVhBaU9pSktWMVFpTENKaGJHY2lPaUpTVXpVeE1pSjkuZXlKamJHbGxiblJoY0hCeWIzWmhiSE4wWVhSMWN5STZJbUZqWTJWd2RDSXNJblJrY3lJNkluUmxjM1FnY21Ga2FYVnpJaXdpZEhoamIzVnVkR1Z5SWpvaU9TSjkuU3FkdWwweGluWUZzenJCblNxWVR4ZUlxSE5zWjJFM3dsdHZELVFrbTRyMWZPMElPUGU5ZGZpdnNzamloSVFnSlVyU25qMGczYW1YSFJjYXVSckxpamhxeE5qREltSk9JZjNmbFNhaFh6NkVsbFN2WHZxYXJQdW9YRWtlMWVMTW93cnpHcTJEWVFxUE5KOVlXa25OWXNKekxkdmYxM1Q5RmFTRG04bm5DRkRqZ3pfMnRIczJLclYzeHhibElqYTlaSFd4YVg3bk1aVTFoOWlHRXRaUnRPMWRoclpLcTRPTU5uSXBSTG9WekhWcDFaeDJrenhkQ2JkakFvR0hkbjNPQVMzd05wcEw1WTVubFpiWlExaW5FYWNWamV5R1pvOXhZZEpZd1ZFVzNGNGNJVlFOUndGdTBRUGFCaTBNUGdaN2ZfU1BZTjJJeWdsVTl5eThNQzdXeWxRPT0iLCJQVUsiOiJNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTRXaktyOEdWWVYrcU9YcjNUbE9VckRWVzZPXC9VMnI3VHhqXC9wSDV6OU4wNjBkWmFwczROUnVEaENuT3FrU3owM0h1aXpPMXVcL2dDc3lXRDRrektkVHlwU2s0ZEpIeXZuMmRqcjlNZ2ozMFF2S1V3Y1NFNUdhencwNDBrOXN3OVJGanl1ZUQ5YTh0YWxhNUNuT1FmT3NoWjg2VitITk8yUFhQdmRxSExBaDZkajFGdXErdzhzU3N3RjJUVExZbnNOVnJselVIbFZFbmhpUjRVQkdENFBRRTZcL3dcL1FOVXdaMjFYdzlPQVlXYm4xcGIxQm9wVjh6aG1qRFFtQlJwU3lGSUtzN2lxOUhPczdpclFcLzMzS3RXYTN6cFZIeXdybEVMRDJMclwveklyd1JGelFHV09aczZ3MGRBWitPSVI3aWdKZFpRXC9KaHZ6dEJMXC9LMHBLUkhsUHJsUUlEQVFBQiIsImlzcyI6Imh0dHBzOlwvXC9oamk5Mi5hZC5nbG9iYWxcL2lkcFwvT05MSU5FQkFOS1wvYXV0aG4iLCJkZXZpY2VpZCI6MTE3MjcsInJlc3VsdCI6MSwiYXVkIjoic3BsLWlkcC1wdXNoLXNlbmRhZnRlciIsImFjciI6IjIiLCJ1cm46b3BlbmlkOnBhcmFtczpqd3Q6Y2xhaW06YXV0aF9yZXFfaWQiOiIzMjcwOTM4My0zNTQyLTQwMjQtOTY1OS00M2Y3MmI4MDNiYjkiLCJhdXRoX3RpbWUiOjE2NDk3ODk1MTIsImNvbnRleHQiOnsiRnJhbWVkLUlQLUFkZHJlc3MiOiIxLjEuMS4xIiwiVXNlci1OYW1lIjoic3BsIn0sImNsaWVudGFwcHJvdmFsc3RhdHVzIjoiYWNjZXB0IiwiZXhwIjoxNjQ5NzkzMTEyLCJpYXQiOjE2NDk3ODk1MTJ9.Q75NlJvT8BX3xHzcth9c9bXXUWDMjXOMd5iB1UA3q92zz1Cfg93lqZHvW3JRWydvsadEtuzBwa2P10PanMp2rDkvh-jrobPALXOOxni3VCtGkMfaSh9eELdv6HMllNB8x_uJQHoRinvXsHtdP3F4RsQ-ilD3VJByNce_M9f7dHywAxbuqQfQNBD-kV56ITckoTnCih93vpJnBwGQqPb_6eSjqKUAQyTu8puwwl9Soo6jtlDeHtarD3QhAjPxTzRfh7hYJ94OssWXwA1U3aX7OPI2IWbsC3NsniVH18rWBr2bGKlVB53gAypM2-IAoQWksnlcM9wvHp_eQefZnbqung",
    "token_type": "Bearer",
    "expires_in": 3600
}
Copy

Where the decoded id_token is:

{
    "at_hash": "A1ifydl-B1V7MqvVZUp56Q",
    "sub": "spl-cust02",
    "reason": "Reason not defined",
    "JWS": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzUxMiJ9.eyJjbGllbnRhcHByb3ZhbHN0YXR1cyI6ImFjY2VwdCIsInRkcyI6InRlc3QgcmFkaXVzIiwidHhjb3VudGVyIjoiOSJ9.Sqdul0xinYFszrBnSqYTxeIqHNsZ2E3wltvD-Qkm4r1fO0IOPe9dfivssjihIQgJUrSnj0g3amXHRcauRrLijhqxNjDImJOIf3flSahXz6EllSvXvqarPuoXEke1eLMowrzGq2DYQqPNJ9YWknNYsJzLdvf13T9FaSDm8nnCFDjgz_2tHs2KrV3xxblIja9ZHWxaX7nMZU1h9iGEtZRtO1dhrZKq4OMNnIpRLoVzHVp1Zx2kzxdCbdjAoGHdn3OAS3wNppL5Y5nlZbZQ1inEacVjeyGZo9xYdJYwVEW3F4cIVQNRwFu0QPaBi0MPgZ7f_SPYN2IyglU9yy8MC7WylQ==",
    "PUK": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4WjKr8GVYV+qOXr3TlOUrDVW6O/U2r7Txj/pH5z9N060dZaps4NRuDhCnOqkSz03HuizO1u/gCsyWD4kzKdTypSk4dJHyvn2djr9Mgj30QvKUwcSE5Gazw040k9sw9RFjyueD9a8tala5CnOQfOshZ86V+HNO2PXPvdqHLAh6dj1Fuq+w8sSswF2TTLYnsNVrlzUHlVEnhiR4UBGD4PQE6/w/QNUwZ21Xw9OAYWbn1pb1BopV8zhmjDQmBRpSyFIKs7iq9HOs7irQ/33KtWa3zpVHywrlELD2Lr/zIrwRFzQGWOZs6w0dAZ+OIR7igJdZQ/JhvztBL/K0pKRHlPrlQIDAQAB",
    "iss": "https://[base-server-url]/{tenant}/authn/token",
    "deviceid": 11727,
    "result": 1,
    "aud": "spl-idp-push-sendafter",
    "acr": "2",
    "urn:openid:params:jwt:claim:auth_req_id": "32709383-3542-4024-9659-43f72b803bb9",
    "auth_time": 1649789512,
    "context": {
        "Framed-IP-Address": "1.1.1.1",
        "User-Name": "spl"
    },
    "clientapprovalstatus": "accept",
    "exp": 1649793112,
    "iat": 1649789512
}

For further information about the tokens, see Making the most of OpenID tokens.

Error/Failure Responses

Code Label Possible Errors

400

BAD REQUEST

  • invalid_request
  • invalid_grant
  • unsupported_grant_type
  • invalid_scope
  • unauthorized_client
  • expired_token
  • authorization_pending
  • hid_failure
  • hid_error
401 UNAUTHORIZED invalid_client
403 FORBIDDEN access_denied
500 INTERNAL SERVER ERROR server_error

HID Authentication Service server failure and error responses conform to the OpenID Connect Core specification - section 3.1.3.4 and OAuth 2. 0 specification - section 5.2, and also define the following claims:

For ‘failure’:

  • [ hid_failure ] – optional, only for password grant:

    • reason – the failure reason code

    • authType – the code of HID Authentication Service authentication type (for example, AT_OPCODE)

For ‘error’:

  • error – an error code which can take on of the following values:

    • hid_error – the error is defined by the given code
  • hid_error – HID custom error, contains an HID error code:

Copy

Sample error response - invalid request

HTTP/1.1 400 Bad Request
Content-Type: application/json;charset=UTF-8
 
{
   "error_description": ":Missing or empty \"code\" parameter",
   "error": "invalid_request"
}
Copy

Sample error response - invalid authentication request ID

HTTP/1.1 400 Bad Request
Content-Type: application/json;charset=UTF-8
 
{
   "error_description": "Invalid grant:CIBA Request Invalid",
   "error": "invalid_grant"
}
Copy

Sample response for failure (password grant)

HTTP/1.1 400 Bad Request
Cache-Control: no-store
Pragma: no-cache
Content-Type: application/json; charset=UTF-8
 
{
    "hid_failure":    {
        "reason": 13,
        "authType": "AT_EMPPWD"
    },
    "error_description": "Invalid grant: Resource owner username or password is invalid (Password does not match):Resource owner username or password is invalid",
    "error": "invalid_grant"
}
Copy

Sample error response - token expired

HTTP/1.1 400 Bad Request
Content-Type: application/json;charset=UTF-8
 
{
   "error_description": "The auth_req_id has expired. The Client will need to make a new Authentication Request.",
   "error": "expired_token"
}
Copy

Sample error response - authorization pending

HTTP/1.1 400 Bad Request
Content-Type: application/json;charset=UTF-8
 
{
   "error_description": "The authorization request is still pending as the end-user hasn't yet been authenticated.",
   "error": "authorization_pending"
}
Copy

Sample error response

HTTP/1.1 400 Bad Request
Cache-Control: no-store
Pragma: no-cache
Content-Type: application/json; charset=UTF-8
 
{
   "hid_error": {"code": "1200"},
   "error_description": "Exception occured: :Resource owner username or password is invalid",
   "error": "hid_error"
}
Copy

Sample response for failure (general)

HTTP/1.1 401 Unauthorized
Cache-Control: no-store
Pragma: no-cache
Content-Type: application/json; charset=UTF-8
 
{
   "error_description": "Client authentication failed: Password does not match: - Client id or secret is invalid",
   "error": "invalid_client"
}