Obtaining an OAuth Access Token
This process assumes you have already created OAuth credentials as described under Create an Access Token.
Understanding the OAuth Client Credentials Flow
The OAuth 2.0 Client Credentials flow enables secure server-to-server authentication. In this flow:
- A client application (server) authenticates itself to the authorization server
- The client receives an access token
- The access token is used to access protected resources
This flow is designed for machine-to-machine (M2M) communication where no user interaction is required.
OAuth Client Credentials in HYPR
HYPR's implementation uses JWT (JSON Web Token) for client assertion in the OAuth 2.0 Client Credentials flow. The client uses its private key to sign a JWT and then exchanges this JWT for an access token.
Key features:
- Security: Uses asymmetric cryptography for authentication
- Replay protection: Each JWT has a unique ID (jti) and short lifespan
- Throttling: Limits the number of active access tokens per client
- Scoped access: Tokens are limited to specific API operations
HYPR has provided a JWT creation signing tool for your convenience.
Step 1: Generate JWT Assertion
-
Download JWTCreator.java (right-click the link and select Save link as...). This vanilla Java code is all you need to generate and sign a JWT token
ℹ️ Needs Java 17+
$ java JWTCreator.java -help
Usage: java JWTCreator [options]
Options:
-help Show this help message and exit
-sub <subject> MANDATORY subject claim. `Client Id` from CC UI token creation screen
-keybase64 <key> MANDATORY base64 private key. `Client key` from the CC UI token creation screen
-exp <expiration> OPTIONAL expiration time of the JWT token created. In seconds since epoch. Default: now() + 1 hour
-out <file> OPTIONAL output file to write the JWT token -
Run the following command to generate the assertion, substituting the
Client ID
andClient Key
values obtained in Create an Access Token:Example command, for a JWT expiring in 6 hours:
java JWTCreator.java \
-sub "hypap-0a2c1e47c4b9dummy" \
-keybase64 "MEECAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQcEJzAlAgEBBCCRAVkCsog/IXLcUxrMrlaijsSQhzZTEZzagSivhmpw5A==" \
-exp $(($(date +%s) + 21600)) -
The resulting JWT will be created in the same folder where
JWTCreator.java
is stored. The contents will be similar to the following example. For reference, see Microsoft identity platform application authentication certificate credentials.Example output:
Use this JWT to exchange for an access token, which lets you authenticate with the API.
eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImZjYzYyMGNjLWVjYjYtNDdmOS05N2ExLWRkMTMwZjRhM2ZiNiJ9.eyAiaXNzIjogImh0dHBzOi8vaHlwci5jb20iLCJzdWIiOiAiaHlwYXAtMGEyYzFlNDdjNGI5ZHVtbXkiLCJhdWQiOiAiaHR0cHM6Ly9oeXByLmNvbSIsImp0aSI6ICJjNjgxOWM2Zi0zODRlLTRiMjEtOTk0YS01NWNjM2UyNWZmY2EiLCJleHAiOiAxNzU4NDMyNDI1LCJpYXQiOiAxNzU4NDI4ODI1LCJuYmYiOiAxNzU4NDI4ODI1IH0.MQaayVLr4N7mXHBlnk7eEVlma8JjWu5hBzDBNXwbq9MsnVpNk6LqWlZHGugFBEu9rf2gOfiGrRsFkkJTOJOuPg
Decoded JWT token
{
"alg": "ES256",
"typ": "JWT",
"kid": "04a04a2c-5440-4cb8-bd3f-3c24af60924a"
}
.
{
"iss": "https://hypr.com",
"sub": "hypap-0a2c1e47c4b9dummy",
"aud": "https://hypr.com",
"jti": "214cf44c-1123-4dbd-a7ec-387b1ee2baa9",
"exp": 1758428668,
"iat": 1758425068,
"nbf": 1758425068
}
.
"eyJhbGciOiJFUzI1NiJ9.eyJzdWIiOiJoeXBh{...}7GFa8A"
The JWT header contains the following important claims:
Claim | Sample value | Description |
---|---|---|
alg | ES256 | The algorithm used to sign the JWT |
typ | JWT | The media type of this complete JWT |
kid | 04a04a2c-5440-4cb8-bd3f-3c24af60924a | The "kid" (key ID) Header Parameter is a hint indicating which key was used to secure the JWS. When used with a JWK, the "kid" value is used to match a JWK "kid" parameter value. |
The JWT body contains the following important claims:
Claim | Sample value | Description |
---|---|---|
sub | hypap-0a2c1e47c4b9dummy | The subject of the JWT (the user). Client Id from CC UI token creation screen |
iss | https://hypr.com | The issuer of the JWT. Must be https://hypr.com |
aud | https://hypr.com | The recipients that the JWT is intended for. Must be https://hypr.com |
jti | 214cf44c-1123-4dbd-a7ec-387b1ee2baa9 | The unique identifier for the JWT. UUID. |
exp | 1758428668 | The expiration time on or after which the JWT MUST NOT be accepted for processing. Time since epoch, in seconds. This is from the -exp param to the JWTCreator.java. Defaults to 1 hour from now. |
iat | 1758425068 | The time at which the JWT was issued. Time since epoch, in seconds. Defaults to now |
nbf | 1758425068 | The time before which the JWT MUST NOT be accepted for processing. Time since epoch, in seconds. Defaults to now |
Step 2: Exchange JWT for Access Token
Take the generated JWT assertion and use it to request an access token from the server:
-
Copy the
client_assertion
(the long string at the end; in this example,eyJhbG...OfiGrRsFkkJTOJOuPg
) and use it to issue a cURL command using the following format:Parameter Value client_assertion_type urn:ietf:params:oauth:client-assertion-type:jwt-bearer
client_assertion The JWT assertion string generated in Step 1; in our example, it is eyJhbG...OfiGrRsFkkJTOJOuPg
.grant_type authorization_code
-
Make the token request:
Sample cURL Commandcurl --location 'https://highlandsbank.hypr.com/rp/token/endpoint/exchange/clientcredentials' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer' \
--data-urlencode 'client_assertion=eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjMyMDU0YmFjLWZmMzktNGYwZi05MDg5LTIyNWRmODFiZDQxMyJ9.eyAiaXNzIjogImh0dHBzOi8vaHlwci5jb20iLCJzdWIiOiAiaHlwYXAtZjZmN2RjNzZiMTBlNDkyOThiNWVkZjNmOWQ3ZTQ5NjUiLCJhdWQiOiAiaHR0cHM6Ly9oeXByLmNvbSIsImp0aSI6ICJhZDE2YzZlYy1kYTU5LTQyM2ItOTQzNi1iMjY1NWMwMTI1ODAiLCJleHAiOiAxNzQ1MDk5NjUxLCJpYXQiOiAxNzQ1MDk2MDUxLCJuYmYiOiAxNzQ1MDk2MDUxIH0.C6Z8dTJKmu030iU3XbuqjWp3EN3TOTI5i_rvR-cxHC2rEhi44uJYzpbpZPAtJE419tgeU4jJuxeNHN0JSwwlFw' \
--data-urlencode 'grant_type=authorization_code' -
The server validates the JWT assertion by:
- Verifying the JWT signature using your client's public key
- Checking that the JWT is not expired
- Ensuring the JWT has not been used before (replay protection)
- Validating the audience, issuer, and subject claims
-
If successful, the server responds with an access token:
This token can be used to make API calls, until it expires
{
"token_type": "Bearer",
"expires_in": 3599,
"access_token": "hypap-f24ae508-356e-4b5b-bc71-dummy",
"scope":"hypr:rp:report hypr:cc:applications"
}Property Description token_type The type of token. In this case, it will always be Bearer
.expires_in The number of seconds before this token expires, as determined by the value of Expires during Create an Access Token. The access token may be used any number of times before it expires. An expired token will receive a 401/403 response. access_token The access token value. Copy and save it for later use. scope A space-separated list of scopes (permissions) granted to this token. -
If the request fails, you'll receive an error response:
{
"error": "invalid_scope",
"error_description": "AADSTS70011: The provided value for the input parameter 'scope' is not valid",
}
Step 3: Make API call
Include the access token in the Authorization header Example:
GET http://localhost:8009/rp/api/bulk/HYPRDefaultApplication/introspect
Authorization: Bearer hypap-f24ae508-356e-4b5b-bc71-dummy
Common Errors and Troubleshooting
Error Code | Description | Possible Causes | Recommended Solutions |
---|---|---|---|
1201023 | Invalid request parameters during token creation | OAuth client credentials used with incorrect scopes • TTL less than 60 seconds | Use OAuth client credentials only for API scopes • Set TTL to minimum 60 seconds |
1201046 | Endpoint API token invalid or expired | Token not found, expired, wrong type, invalid scope, or rpAppId mismatch | Verify token exists • Generate new token • Use CLIENT_CREDENTIALS type • Check scope and rpAppId |
1201047 | Invalid token exchange request | Missing JWKS URL, signature verification failed, expired JWT, invalid claims, missing keyID header | Provide valid JWKS URL • Ensure proper JWT signing • Check expiration and claims • Include keyID header |
1201093 | OAuth request throttled | Excessive requests for JWT token exchanges | Reduce request frequency • Review implementation for proper reuse. Once a JWT token is exchanged, use it until expiry. Similarly, re-use the access token until it expires. |
Security Best Practices
- Protect private keys: Store your private key securely
- Short-lived JWTs: Use short expiration times for JWTs (typically 5-10 minutes)
- Minimize scopes: Request only the scopes needed for your application