Agora

Personal Access Tokens

Issue, list, and revoke PATs; validate them by introspection.

Personal Access Tokens (PAT) are long-lived credentials for machine-to-machine access — CI jobs, scripts, integrations — that authenticate without the interactive OIDC flow.

Enabling PAT

PAT requires a patStore on the server and a shared patIntrospectionSecret:

config/authkit.ts
import PersonalAccessToken from '#models/personal_access_token'
import { lucidPatStore } from '@adonis-agora/authkit-server'

defineConfig({
  // ...
  patStore: lucidPatStore(PersonalAccessToken),
  patIntrospectionSecret: env.get('PAT_INTROSPECTION_SECRET'),
})

The model uses the withPersonalAccessToken mixin. The PatStore contract covers issuing, listing, revoking, and lookup; lucidPatStore(Model) is the default implementation.

Issue / list / revoke

The account console (mounted by registerAuthHost) exposes the user-facing management UI:

RouteAction
GET /account/tokensList the signed-in account's tokens
POST /account/tokensIssue a new token (the plaintext value is shown once)
POST /account/tokens/:id/revokeRevoke a token

Tokens are generated with generatePatToken() and only the hash (hashPatToken()) is persisted — the raw value is returned to the user exactly once at issue time.

Introspection (machine-to-machine)

A relying party validates an inbound PAT by calling the IdP's introspection endpoint, authenticated with the shared secret:

POST {issuer}/authkit/pat/introspect

On the client side, use resolvers.pat so this happens automatically per request:

config/authkit_client.ts
resolver: resolvers.pat({
  introspectionUrl: `${env.get('AUTHKIT_ISSUER')}/authkit/pat/introspect`,
  introspectionSecret: env.get('PAT_INTROSPECTION_SECRET'),
})

A valid, non-revoked token introspects to an Identity just like a session JWT, so the rest of your app (resolveUser, policies) is unchanged.

The introspection route can be rate-limited via the introspection bucket — see Security. PAT issue/revoke/use also emit audit events (pat.issued, pat.revoked, pat.used).

On this page