---
title: "Migrate from @maximemrf/adonisjs-jwt"
description: "Replace the legacy guard safely without accepting old tokens under weaker rules."
image: "https://adonisjs-jwt.pages.dev/og.png"
---

> Documentation Index
> Fetch the complete documentation index at: https://adonisjs-jwt.pages.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Migrate from @maximemrf/adonisjs-jwt

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

```sh
node ace add @rikology/adonisjs-jwt
node ace jwt:make-key
node ace migration:run
```

Use 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](/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.

Source: https://adonisjs-jwt.pages.dev/migration/index.mdx
