Skip to content

Test and maintain the server

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:

tests/functional/api.spec.ts
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.

Register a listener in start/events.ts:

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.

Run the purge command from your application’s existing scheduler:

Terminal window
node ace sesame:purge --hours=168

The 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.

To purge old registrations that never authorized, add --clients:

Terminal window
node ace sesame:purge --clients --client-days=30

For 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.