Integrate

Verifying access tokens

Check your users' access tokens offline, with your app's public keys (RS256).

How tokens are signed

Every access token Identise hands your app is signed RS256 with a key of your app's own, which only Identise holds. Your services verify tokens with that key's public half, from /apps/{appId}/.well-known/jwks.json, so they need no secret at all.

Your API key is only for your backend's calls to Identise: keep it on those servers, and out of every service that only checks tokens.

What to check

AlgorithmOnly RS256.
KeyThe one the token's kid header names, from your app's JWKS.
audYour App ID.
issYour Identise deployment's issuer: the issuer in your app's /apps/{appId}/.well-known/openid-configuration.
expRequired. No clock skew needed: the tokens last minutes (15 by default).

Claims

subThe user's id. Use it as your foreign key, not the email.
emailThe user's email.
email_verified, mfa_enabledThe strings "true" or "false".
statusActive, PendingVerification or Suspended.

Verifying tokens

Point your JWT library at the keys and pin the algorithm. The libraries below cache the keys and fetch them again when a token names one they haven't seen.

ASP.NET Core

csharp
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>
{
    // Your app's own authority: finds its keys through /.well-known/openid-configuration below it,
    // caches them, and fetches them again when a token names a key it hasn't seen
    options.Authority = $"https://api.identise.com/apps/{identise.AppId}";
    options.MapInboundClaims = false;
    options.TokenValidationParameters = new TokenValidationParameters
    {
        ValidIssuer = identise.Issuer,
        ValidAudience = identise.AppId,
        ValidAlgorithms = [SecurityAlgorithms.RsaSha256],
        ClockSkew = TimeSpan.Zero
    };
});

Node (jose)

ts
import { createRemoteJWKSet, jwtVerify } from "jose";

// Your app's own keys: fetched on first use, cached, and fetched again when a token names a key it hasn't seen
const identiseKeys = createRemoteJWKSet(
    new URL(`https://api.identise.com/apps/${process.env.IDENTISE_APP_ID}/.well-known/jwks.json`),
);

export async function verifyIdentiseToken(token: string) {
    const { payload } = await jwtVerify(token, identiseKeys, {
        algorithms: ["RS256"],
        audience: process.env.IDENTISE_APP_ID,
        issuer: process.env.IDENTISE_ISSUER,
    });
    return { userId: payload.sub!, email: payload.email as string, emailVerified: payload.email_verified === "true" };
}

Python (PyJWT)

python
import jwt

identise_keys = jwt.PyJWKClient(f"https://api.identise.com/apps/{IDENTISE_APP_ID}/.well-known/jwks.json")

def verify_identise_token(token):
    key = identise_keys.get_signing_key_from_jwt(token)
    return jwt.decode(token, key.key, algorithms=["RS256"], audience=IDENTISE_APP_ID, issuer=IDENTISE_ISSUER)

Your app's keys

Every app has keys of its own, held by Identise: another app's tokens never verify with yours.

Wherehttps://api.identise.com/apps/{appId}/.well-known/jwks.json: public, cacheable for 5 minutes. An App ID that doesn't exist is a 404.
RotationA key signs for 90 days. The next one is published from the start, and a replaced key stays published 24 hours after, so every token you meet has a key you have already fetched.
Revoking an API keyRevoking, rotating or deleting one of your API keys (or your app being suspended) hands over to the next signing key at once and stops publishing the old one. Tokens issued before then, perhaps by someone holding a leaked key, stop verifying as soon as your service fetches the JWKS again: restart it, or clear its key cache, to cut them off at once. New tokens use a key you already have.
Discovery/apps/{appId}/.well-known/openid-configuration gives the issuer, the jwks_uri and the claims, for libraries that start from an authority: use https://api.identise.com/apps/{appId}.

Rotating an API key

Tokens don't depend on your API key, so rotate it whenever you like:

  1. 1

    Generate the new key

    In the dashboard, under the app's API Keys.

  2. 2

    Deploy it

    To every server that calls Identise.

  3. 3

    Revoke the old key

    Your app's signing key hands over with it, so access tokens issued before stop verifying once your services fetch the JWKS again; your users simply refresh.

Pin the algorithm: never accept none, never let a token's own alg header choose how it is checked, and never skip the aud check: it is what stops one app's tokens from working in another.