Skip to main content

Auth and tokens

authenik8-core 2.x uses JOSE with ES256 P-256 JWKs for new applications. Generate a private signing key once, persist it in a secret manager, and load the same key ring on every process start.

Use the engine's generator during one-time bootstrap or reviewed rotation tooling, never during application startup:

import {generateSigningJwk} from 'authenik8-core';

const signingKey = await generateSigningJwk();
auth.ts
import {createAuthenik8} from 'authenik8-core';

const auth = await createAuthenik8({
jwt: {
keys: JSON.parse(process.env.AUTHENIK8_SIGNING_JWKS!),
activeKid: process.env.AUTHENIK8_ACTIVE_KID!,
issuer: process.env.AUTHENIK8_ISSUER!,
audience: process.env.AUTHENIK8_AUDIENCE!,
},
refreshSecret: process.env.REFRESH_SECRET!,
});

Generated projects provide an authJwkConfig() helper that validates these values before constructing the engine.

Issue a session

Call issueTokens only after the application authenticates the human or establishes another trusted identity boundary:

const tokens = await auth.issueTokens({
userId: user.id,
email: user.email,
role: user.role.toLowerCase(),
});

Do not expose an endpoint that accepts an arbitrary userId and passes it directly to issueTokens.

The access and refresh tokens share a sessionId. Access tokens are ES256 JWTs. Refresh tokens are purpose-bound JOSE tokens whose current value is tracked in Redis.

Verify requests

Use the session-aware middleware on application routes:

app.get('/protected', auth.requireAuth, (req, res) => {
res.json({user: req.user});
});

Direct verification is asynchronous:

const payload = await auth.verifyToken(tokens.accessToken);

Publish public keys

app.get('/.well-known/jwks.json', (_req, res) => {
res.json(auth.getJwks());
});

getJwks() strips private fields. Verification enforces ES256, kid, issuer, audience, expiry, and token purpose.

For a separate service, use verifyAccessTokenWithJwks() with a local key set or trusted JWKS URL. Signature verification alone cannot observe Redis revocation, so sensitive routes should retain a session-aware boundary.

For generated projects, prefer the CLI's two-phase operational rotation. It generates, signs, publishes, and verifies through the installed engine contract before changing the active key.

Legacy migration

jwtSecret remains only as a deprecated HS256 migration path. New applications should use the jwt JWK configuration.