This is a clean cutover, not a drop-in rename. The legacy package exposes generate,
generateWithRefreshToken, revoke, tokenName, useCookies, a shared secret, arbitrary token
content, and optional jwks-rsa verification. This package uses strict claims, a separate JWT
config, login/refresh/logout, transport objects, and refresh-family replay detection.
1. Install beside the old guard
node ace add @rikology/adonisjs-jwt
node ace jwt:make-key
node ace migration:runUse a new refresh table during rollout if both guards must remain live briefly. Do not point both packages at one table: the row shape and rotation semantics differ.
2. Replace configuration
| Legacy option or method | Replacement |
|---|---|
secret (often APP_KEY) |
Independent Ed25519 PEMs, or a 32-byte minimum HS256 secret |
tokenExpiresIn |
access.expiresIn |
useCookies, tokenName, cookie |
transports.cookie({ ... }) |
refreshTokenExpiresIn |
refresh.expiresIn |
refreshTokenAbilities |
Not used; refresh tokens are purpose-specific opaque values |
content(user) |
Fixed registered claims plus optional scope and roles |
jwks.jwksUri |
keyDrivers.remoteJwks({ url }) verification-only mode |
generate(user) |
login(user) |
generateWithRefreshToken() |
refresh(rawRefreshToken?) |
revoke() |
logout(rawRefreshToken?) or logoutAll(user) |
Register the exact guard shown in Configuration. Keep issuer and audience explicit; do not weaken them to make old tokens pass.
3. Update endpoints and clients
The new login response uses tokenType, accessToken, expiresIn, refreshToken, and
refreshExpiresIn. Refresh rotation returns a replacement refresh token every time. Update clients
to persist that replacement atomically.
Cookie clients must echo the readable jwt_csrf cookie in x-csrf-token on unsafe methods. The
legacy useCookies: true setting alone did not establish this double-submit contract.
4. Plan token invalidation
Legacy access JWTs do not necessarily contain this package’s required issuer, audience, kid,
jti, and type: 'access' claims. They are intentionally rejected. Choose one cutover:
- require all users to sign in again at deployment; or
- keep the old guard on isolated legacy routes for no longer than the old access and refresh TTLs, while issuing only new-format sessions from the primary login route.
Never make one endpoint accept both claim sets indefinitely. Remove the legacy guard, routes, secret, dependencies, and table only after the overlap expires.
5. Verify before removal
- New login and protected routes work in bearer and/or cookie mode.
- Refresh replaces the token; replay after the grace window revokes the family.
- Logout and logout-all revoke the expected sessions.
- Wrong issuer/audience, old-format tokens, and legacy signing keys are rejected.
- JWKS exposes public fields only and downstream caches observe the active
kid. - No application log or telemetry field contains access or refresh token values.