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 signing tool for your convenience. You may use any JWT signing program to accomplish this process, as long as it conforms to convention.
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
-
Run the following command to generate the assertion, substituting the
client_id
andclient_private_key
values obtained in Create an Access Token:java JWTCreator.java -sub "<client id>" -keybase64 "<client private key>"
Example:
java JWTCreator.java -sub "hypap-f6f7dc76b10e49298b5edf3f9d7e4965" -keybase64 "MEECAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQcEJzAlAgEBBCCRAVkCsog/IXLcUxrMrlaijsSQhzZTEZzagSivhmpw5A=="
-
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.{
"alg": "ES256",
"typ": "JWT",
"kid": "ed2e03e9-fd91-4492-962d-0791980a4d6d"
}
.
{
"iss": "https://hypr.com",
"sub": "hypap-f6f7dc76b10e49298b5edf3f9d7e4965",
"aud": "https://hypr.com",
"jti": "eea97eb7-b463-4a51-9a49-93291a192cc0",
"exp": 1745099316,
"iat": 1745095716,
"nbf": 1745095716
}
.
"eyJhbGciOiJFUzI1NiJ9.eyJzdWIiOiJoeXBh{...}7GFa8A"
The JWT contains the following important claims:
Claim | Description |
---|---|
sub (Subject) | Your client ID (same as issuer) |
aud (Audience) | The token endpoint URL |
jti (JWT ID) | A unique identifier for this JWT |
exp (Expiration Time) | When the JWT expires (typically a short duration from now) |
iat (Issued At) | When the JWT was issued |
nbf (Not Before) | The time before which the JWT must not be accepted |
iss (Issuer) | The entity that issued the JWT (typically your client ID) |
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...7GFa8A
) 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...7GFa8A
.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:
{
"token_type": "Bearer",
"expires_in": 3599,
"access_token": "eyJ0eXAiOiJKV1QiLCJhbRciOiJSUzI1NiI",
"scope":"hypr:adapt:readPolicy 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. 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",
}
Common Errors and Troubleshooting
Error | Possible Causes | Solution |
---|---|---|
Invalid client | Client ID is incorrect or not registered | Verify client ID |
Invalid JWT signature | Private key doesn't match registered public key | Check key pair |
JWT expired | The JWT's expiration time has passed | Generate a new JWT |
JWT already used | Attempting to reuse a JWT with the same JTI | Generate a new JWT with a unique JTI |
Too many tokens | Client has reached maximum number of active tokens | Wait for tokens to expire or revoke existing tokens |
Security Best Practices
- Protect private keys: Store your private key securely
- Short-lived JWTs: Use short expiration times for JWTs (typically 5-10 minutes)
- Unique JTIs: Ensure each JWT has a unique identifier
- Validate certificates: For production use, validate certificate chains
- Minimize scopes: Request only the scopes needed for your application