Verify Access Tokens for Custom APIs
When a custom API receives a request with a bearer Access Token, the first thing to do is to validate the token.
At Auth0, an Access Token used for a custom API is formatted as a JSON Web Token which must be validated before use.
Validating the token consists of a series of steps, and if any of these fails, then the request must be rejected. This document lists all the validations that your API should perform:
- Check that the JWT is well formed
- Check the signature
- Validate the standard claims
- Check the Application permissions (scopes)
Parse the JWT
First, the API needs to parse the JSON Web Token (JWT) to make sure it's well formed. If this fails the token is considered invalid and the request must be rejected.
A well formed JWT, consists of three strings separated by dots (.): the header, the payload and the signature. Typically it looks like the following:
The header and the payload are Base64Url encoded. The signature is created using these two, a secret and the hashing algorithm being used (as specified in the header: HMAC, SHA256 or RSA).
For details on the JWT structure refer to What is the JSON Web Token structure?.
How can I parse the JWT?
In order to parse the JWT you can either manually implement all the checks as described in the specification RFC 7519 > 7.2 Validating a JWT, or use one of the libraries listed in the Libraries for Token Signing/Verification section of JWT.io.
For example, if your API is implemented with Node.js and you want to use the node-jsonwebtoken library, then you would call the jwt.verify() method. If the parsing fails then the library will return a JsonWebTokenError error with the message
We should note here that many web frameworks (such as ASP.NET Core for example) have JWT middleware that handle the token validation. Most of the times this will be a better route to take, rather that resorting to use a third-party library, as the middleware typically integrates well with the framework's overall authentication mechanisms.
How can I visually inspect a token?
A quick way to see what is inside a JWT is by using the JWT.io website (alternatively, you can use the JWT Debugger Chrome Extension). It has a handy debugger which allows you to quickly check that a JWT is well formed, and also inspect the values of the various claims.
Just paste your token at the Encoded text area and review the decoded results at the right.
Check the Signature Algorithm
The API needs to check if the algorithm, as specified by the JWT header (property
alg), matches the one expected by the API. If not, the token is considered invalid and the request must be rejected.
In this case the mismatch might be due to mistake (it is common that the tokens are signed using the
HS256 signing algorithm, but your API is configured for
RS256, or vice versa), but it could also be due to an attack, hence the request has to be rejected.
How can I check the signature algorithm?
To check if the signature matches the API's expectations, you have to decode the JWT and retrieve the
alg property of the JWT header.
Alternatively, you can use one of the libraries listed in the Libraries for Token Signing/Verification section of JWT.io.
Following the Node.js example of the previous section, the jwt.verify() method of the node-jsonwebtoken library, supports an
algorithms argument, that contains a list of strings with the names of the allowed algorithms.
Verify the signature
The API needs to verify the signature of each token.
This is necessary to verify that the sender of the JWT is who it says it is and to ensure that the message wasn't changed along the way.
Remember that the signature is created using the header and the payload of the JWT, a secret and the hashing algorithm being used (as specified in the header: HMAC, SHA256 or RSA). The way to verify it, depends on the hashing algorithm:
HS256, the API's Signing Secret is used. You can find this information at your API's Settings. Note that the field is only displayed for APIs that use
RS256, the tenant's JSON Web Key Set (JWKS) is used. Your tenant's JWKS is
The most secure practice, and our recommendation, is to use
How can I verify the signature?
To verify a token's signature, you can use one of the libraries available in JWT.io.
Following the Node.js example of the previous section, the jwt.verify() method supports a
secretOrPublicKey argument. This should be populated with a string or buffer containing either the secret (for
HS256), or the PEM encoded public key (for
Where can I find my public key?
Go to Dashboard > Applications. Open the Settings of your application, scroll down and open Advanced Settings. Open the Certificates tab and you will find the Public Key in the Signing Certificate field.
If you want to verify the signature of a token from one of your applications, we recommend getting it by parsing your tenant's JSON Web Key Set (JWKS). Your tenant's JWKS is
For more info on RS256 and JWKS see Navigating RS256 and JWKS.
If the verification fails you will get a
invalid signature error.
Validate the Claims
Once the API verifies the token's signature, the next step is to validate the standard claims of the token's payload. The following validations need to be made:
- Token expiration: The current date/time must be before the expiration date/time listed in the
expclaim (which is a Unix timestamp). If not, the request must be rejected.
- Token issuer: The
issclaim denotes the issuer of the JWT. The value must match the one configured in your API. For JWTs issued by Auth0,
issholds your Auth0 domain with a
https://prefix and a
https://YOUR_AUTH0_DOMAIN/. If you are using the custom domains feature, the value will instead be in the following format:
- Token audience: The
audclaim identifies the recipients that the JWT is intended for. For JWTs issued by Auth0,
audholds the unique identifier of the target API (field Identifier at your API's Settings). If the API is not the intended audience of the JWT, it must reject the request.
Auth0 issues tokens with the iss claim of whichever domain you used with the request. Custom domain users might use either, their custom domain, or their Auth0 domain. For example, if you used https://northwind.auth0.com/authorize... to obtain an Access Token, the iss claim of the token you receive will be https://northwind.auth0.com/. If you used your custom domain https://login.northwind.com/authorize..., the iss claim value will be https://login.northwind.com/.
If you get an Access Token for the Management API using an authorization flow with your custom domain, you must call the Management API using the custom domain (your token will be considered invalid otherwise).
How can I validate the claims?
To validate the claims, you have to decode the JWT, retrieve the claims (
aud) and validate their values.
The easiest way however, is to use one of the libraries listed in the Libraries for Token Signing/Verification section of JWT.io. Note that not all libraries validate all the claims. In JWT.io you can see which validations each library supports (look for the green check marks).
audto the Identifier of the API
issuer: string or array of strings of valid values for the
ignoreExpiration: set to
falseto validate the expiration of the token
Check the Permissions
By now you have verified that the JWT is valid. The last step is to verify that the application has the permissions required to access the protected resources.
To do so, you need to check the scopes of the decoded JWT. This claim is part of the payload and it is a space-separated list of strings.
How can I check the permissions?
To check the permissions granted to the application, you need to check the contents of the
For example, a user management API might provide three endpoints to read, create or delete a user record:
/delete. We have configured this API, so each endpoint requires a specific permission (or scope):
read:usersscope provides access to the
create:usersscope provides access to the
delete:usersscope provides access to the
If a request requests to access the
/create endpoint, but the
scope claim does NOT include the value
create:users, then the API should reject the request with
You can see how to do this, for a simple timesheets API in Node.js, in this document: Check the Application permissions.
You can find a sample API implementation, in Node.js, in Server Application + API: Node.js Implementation for the API.
This document is part the Server + API Architecture Scenario, an implementation of a Client Credentials grant for a hypothetical scenario. For more information on the complete solution refer to Server + API Architecture Scenario.