Test and maintain the server
Authenticate an API test
Section titled “Authenticate an API test”With Japa’s API client and Auth integration configured, use loginAs with the OAuth guard. This example assumes a Lucid User and an existing user fixture:
import { test } from '@japa/runner'import User from '#models/user'
test('returns the authenticated user', async ({ client }) => { const user = await User.findOrFail(1)
const response = await client.get('/api/me').withGuard('oauth').loginAs(user)
response.assertStatus(200) response.assertBodyContains({ id: user.id })})The guard creates a database access token and a shared __test_client__ client on first use. The token has its own grant and uses your configured defaultScopes. A resource-specific guard binds the test token to that resource. Keep those scopes compatible with the endpoint under test.
To set scopes and context for a test request, pass options to loginAs:
await client.get('/api/me').withGuard('oauth').loginAs(user, { scopes: ['read'], context: { teamId: 1 },})Declare the context shape with grant context types if your application uses typed context.
Use separate authorization-flow tests for PKCE, callbacks, consent expiry, and refresh token rotation. loginAs bypasses those flows.
Observe authentication failures
Section titled “Observe authentication failures”Register a listener in start/events.ts:
import emitter from '@adonisjs/core/services/emitter'import logger from '@adonisjs/core/services/logger'
emitter.on('oauth_auth:authentication_failed', (event) => { logger.warn({ guardName: event.guardName, err: event.error }, 'OAuth authentication failed')})Use err for the error so Pino serializes its stack. Do not log raw tokens or secrets. See the events reference for the other guard events.
Purge old records
Section titled “Purge old records”Run the purge command from your application’s existing scheduler:
node ace sesame:purge --hours=168The default removes revoked records and expired records beyond the retention window. Use --revoked to select revoked records or --expired to select expired records.
For application code, call the manager:
import sesame from '@julr/sesame/services/main'
const result = await sesame.purgeTokens({ retentionHours: 168 })Choose retention before scheduling purge. Revoked refresh tokens remain until the retention cutoff so replay detection works. See purge flags and counts for selection behavior.
Remove unused dynamic clients
Section titled “Remove unused dynamic clients”To purge old registrations that never authorized, add --clients:
node ace sesame:purge --clients --client-days=30For application code, call sesame.purgeUnusedClients({ olderThanDays: 30 }). The age must be a positive integer.
Only dynamic clients without authorization history or related OAuth records qualify. Manually created clients and metadata document clients are excluded. See eligibility and metadata markers before writing registration metadata yourself.