Authentication
Declare authentication as a first-class part of your service spec. Each operation identifies the auth scheme it requires by type, and code generators turn that into the matching runtime check — no JSON attributes, no string parsing, no per-controller glue.
1 Declare Auth Schemes on the Service
Add an auth_schemes array at the top level of your api.json. Each entry
declares a scheme type that operations can reference. Code generators look
up the type and emit the corresponding runtime helper.
"auth_schemes": [
{
"type": "hackathon_admin",
"description": "Tenant admin for the hackathon tenant"
},
{
"type": "session",
"description": "Any logged-in user session"
}
] The reserved value none cannot be used as a scheme type — it is the
explicit-public marker on operations.
2 Reference a Scheme on an Operation
Set auth on the operation to one of the declared scheme types. Code generators emit the matching runtime check; the service method receives the authenticated caller as its first argument.
"resources": {
"event": {
"operations": [
{
"method": "GET",
"path": "/admin/events",
"auth": "hackathon_admin"
}
]
}
}3 Resource-Level Defaults & Per-Operation Overrides
In your input api.json you can set a default auth at the resource level so every operation inherits it. API Builder materializes the inheritance for you — the emitted service spec carries the effective scheme on each operation directly. Generators never need to walk back to the resource to find the auth value.
"resources": {
"event": {
"auth": "hackathon_admin",
"operations": [
{ "method": "GET", "path": "/admin/events" },
{ "method": "POST", "path": "/admin/events" },
{
"method": "GET",
"path": "/admin/events/public-feed",
"auth": "none"
}
]
}
} Use "auth": "none" to opt a single operation out of an otherwise-protected
resource. The generated controller emits no auth check for that op.
4 What Generators Produce
The Play controller generator wraps each protected operation in the runtime helper that matches the scheme type and passes the authenticated principal to your service method:
def getEvents(): Action[AnyContent] = Action.async { request =>
withHackathonAdmin(request) { auth =>
service.getEvents(auth).map(toGetEventsResult)
}
} Each generator decides how scheme types map to runtime helpers. If your generator does not recognize a scheme type, codegen fails — an unrecognized scheme is never silently dropped to public.
! Key Rules
- Declare before reference — every
operation.authvalue (other thannone) must appear inservice.auth_schemes. Generators reject unknown references. - Reserved value —
nonecannot be used as an auth_scheme type; it is the per-operation public marker. - Inheritance is materialized — resource-level defaults are flattened into each operation before the spec is emitted, so generators only ever read
operation.auth. - Absent today, required tomorrow — an operation with no
authfield is currently treated as public. A future revision will require the field; declare schemes now to be ready.
Resources
- api.json specification — Full format reference
- Code Generators — How auth schemes flow through generated code
Ready to declare your auth schemes?
View api.json Format