Skip to main content

Roles & Access Control

Nexa uses JWT bearer auth with role-based guards. Roles are scoped — an operator's authority is bounded by airport or tenant.

Roles

RoleScopeCapabilities
ADMINTenant-wideEverything, including policy publishing, PSP token management, agent config
OPS_SUPERVISORTenantPolicy activation, demand approval, allocation override, manual booking, case reopen
AIRPORT_OPERATORAirportClaim + resolve manual review, close cases, manual notification resend
FINANCETenantRead-only on reservations, contracts, savings reports
PASSENGERSelfRead their own voucher (passenger portal)

A user can hold multiple roles; the union of permissions applies.

JWT claims

Bearer tokens are required on every endpoint except /version and the passenger portal's public lookup. Expected claims:

{
"sub": "urn:nexa:user:abc",
"roles": ["OPS_SUPERVISOR"],
"tenant": "airline-xx",
"airports": ["MAD", "BCN"],
"iat": 1713800000,
"exp": 1713803600
}
  • tenant — the airline / organization.
  • airports — the airport IATA codes this user can act on (for AIRPORT_OPERATOR).

A request to /cases/urn:nexa:case:gru-xxx from a user with airports: ["MAD"] returns 403.

Identity provider

Nexa doesn't ship an identity provider. Typical setups:

  • Airline SSO (Okta, Azure AD, Ping) with a Nexa-specific app that maps groups to roles.
  • Auth0 (the operations UI uses it by default in dev).
  • Machine accounts for airline upstream integrations, with long-lived tokens scoped to POST /cases only.

The JWT is validated against the IdP's JWKS endpoint. Configure:

AUTH_JWKS_URI=https://airline.okta.com/oauth2/default/v1/keys
AUTH_ISSUER=https://airline.okta.com/oauth2/default
AUTH_AUDIENCE=nexa-api

Adding a new role

Roles are enum-typed (src/nexa/auth/role.ts). To add a role:

  1. Add the enum value.
  2. Add the role to the guards that should accept it (decorators are per-controller).
  3. Update this page 😊.

Role additions go through review; avoid inventing a role when an existing one plus airport scoping does the job.

Rate limiting

Per-user rate limits protect expensive endpoints:

  • /policies/synthesize — 20 req / user / hour
  • POST /cases — 60 req / user / min
  • POST /manual-review/:urn/rebook — 30 req / user / min

Machine accounts (airline upstream) get separate, higher limits negotiated per contract.

Audit

Every endpoint that changes state requires:

  • A valid bearer token.
  • A reason, for manual actions — enforced by the controller.

The audit entry includes actor, tokenId, ip, reason, and a before/after snapshot. See Audit.

Was this helpful?