Skip to main content

How to verify Authress JWT access tokens

(For information about OAuth, check out the OAuth FAQ)

Background

Authress generates unique EdDSA JWT signed access tokens. These tokens are signed using an asymmetric key algorithm. The public keys for your account are located at:

https://custom-domain.company.com/.well-known/openid-configuration/jwks

In the case that you haven't set up your custom domain yet, the keys are also located at:

https://Authress_Account_ID.login.authress.io/.well-known/openid-configuration/jwks

You can get your accountId by visiting the Authress API in the management portal.

Key lifetime

The Authress public key can and should be cached to avoid unnecessary lookups. However, it is important to not cache indefinitely. In rare events the key will rotate. It may be rotated through a security generated event in Authress or through the management portal. Given this possibly, it is important to be prepared to handle key rotation and expiry.

Additionally, it is the case that your Authress account can and will have multiple active keys at the same time. While not all of these keys will be relevant to signing access tokens, handling for multiple keys is required.

Verification

Getting the public key is only the first step. Once you have the public keys fetched from the URLs above, you can verify incoming JWTs by the following process.

  1. Decode the JWT - Every JWT is a base64 encoded string. This string can be decoded to a JSON object.
  2. Pull out the KeyId (kid) and the Issuer (iss) url - The issuer is Authress, and when using a custom domain, it is this domain. Authress stores multiple public keys for you, and can be identified using the kid property.
  3. Use the issuer url to fetch the public key from the jwks endpoint - Your apis are vulnerable without verifying the incoming token. Anyone can make a JWT, using the issuer's public keys is the only way to ensure your apis are secure.
  4. Verify the signature of the JWT using the public key - In the case the signature is not valid, reject the request.

Once you have verified the signature, you can identify the user by using the Subject claim (sub) of the token.

To simplify the steps above the most of the Authress SDKs contain a TokenVerifier class or method to enable easy access to verifying Authress tokens. The use of the SDK is not required, however due to the complexity of doing this they are recommended. A list of SDKs is available in the Authress API Portal.

Example Verifiers

AWS Lambda Authorizer

awsLambdaAuthorizer.js
const { TokenVerifier } = require('authress-sdk');
const cookieManager = require('cookie');
const Api = require('openapi-factory');

let api = new Api({});
module.exports = api;

api.setAuthorizer(async request => {
let authorization = Object.keys(request.headers).find(key => key.match(/^Authorization$/i));

let token = request.headers[authorization] ? request.headers[authorization].split(' ')[1] : null;
if (!token) { throw Error.create('Unauthorized'); }

try {
const cookies = cookieManager.parse(request.headers.cookie || '');
const userToken = cookies.authorization || request.headers.Authorization.split(' ')[1];
// The url should be your custom domain => https://authress.io/app/#/setup?focus=domain
const authressCustomDomain = 'https://login.application.com';
const userIdentity = await TokenVerifier(authressCustomDomain, userToken);

const policy = {
principalId: userIdentity.sub,
policyDocument: {
Version: '2012-10-17',
Statement: [
{
Effect: 'Allow',
Action: ['execute-api:Invoke'],
Resource: ['arn:aws:execute-api:*:*:*']
}
]
},
context: {
jwt: userToken,
principalId: userIdentity.sub
}
};
return policy;
} catch (error) {
throw Error('Unauthorized');
}
});