Skip to content

Configuration

Register the JWT guard and configure algorithms, storage, transports, and revocation.

Register config/auth.ts

The configure hook exports an initialized key set and refresh store from config/jwt.ts. Use this exact guard registration:

import { defineConfig } from '@adonisjs/auth'
import { jwtGuard } from '@rikology/adonisjs-jwt'
import { lucidJwtUserProvider } from '@rikology/adonisjs-jwt/providers'
import jwtConfig, { jwtKeySet, jwtRefreshTokenStore } from '#config/jwt'

const authConfig = defineConfig({
  default: 'jwt',
  guards: {
    jwt: jwtGuard({
      provider: lucidJwtUserProvider({ model: () => import('#models/user') }),
      keySet: jwtKeySet,
      refreshStore: jwtRefreshTokenStore,
      config: jwtConfig,
    }),
  },
})

export default authConfig

Protect routes with middleware.auth({ guards: ['jwt'] }). Authenticated requests expose the validated access claims as ctx.jwtClaims.

Generated config/jwt.ts

The default is Ed25519, 10-minute access tokens, 30-day non-sliding refresh tokens, bearer transport, and a public JWKS route:

const jwtConfig = defineJwtConfig({
  issuer: env.get('JWT_ISSUER'),
  audience: env.get('JWT_AUDIENCE'),
  access: {
    algorithm: 'EdDSA',
    expiresIn: '10m',
    clockTolerance: '30s',
  },
  refresh: {
    expiresIn: '30d',
    sliding: false,
    reuseGraceMs: 2_000,
    table: 'jwt_refresh_tokens',
    prefix: 'rt_',
    tokenSecretLength: 40,
  },
  keys: keyDrivers.env({ privateKeyPem, publicKeyPem, kid: env.get('JWT_KID') }),
  jwks: {
    enabled: true,
    route: '/.well-known/jwks.json',
    cacheMaxAge: 3_600,
  },
  transport: transports.bearer(),
  denylist: { enabled: false },
})

Durations accept seconds, minutes, hours, days, weeks, and years, including decimals such as 1.5h. Set clock tolerance only high enough for measured clock skew.

Algorithms and key drivers

Mode Configuration Signing JWKS output
EdDSA / ES256 / PS256 / RS256 keyDrivers.env({ privateKeyPem, publicKeyPem, kid }) Yes Public key
HS256 keyDrivers.env({ secret, kid }) Yes Empty; symmetric secrets are never published
Encrypted database keyDrivers.database({ table }) Yes Active and overlapping public keys
External identity provider keyDrivers.remoteJwks({ url, ...cacheOptions }) No Cached public remote keys

HS256 secrets must contain at least 32 bytes and must be generated independently from APP_KEY. Remote JWKS mode is verification-only: login and token issuance intentionally fail.

Transport

Bearer mode reads only a strict Authorization: Bearer <token> header. Cookie mode is for first-party browser clients and requires the CSRF contract documented in Browser cookies and CSRF.

Optional immediate revocation

Without a denylist, logout stops renewal while an access JWT remains valid until its short expiry. Pass MemoryDenylist for one-process development or CacheDenylist with a shared Adonis Cache backend in production. Entries contain only the jti and expire with the token.

Navigation

Type to search…

↑↓ navigate↵ selectEsc close