Authorize verified requests¶
Authentication tells you who the caller is; authorization decides what they may do.
authn keeps these separate: once a Verifier returns an Identity, an
AuthorizeFunc
predicate makes the allow/deny call. The package ships no policy engine — you compose
the built-in combinators or supply your own function.
The predicate¶
An AuthorizeFunc receives the verified identity (and, via the context, the request
metadata) and returns true to allow or false to deny:
var authorize authn.AuthorizeFunc = func(ctx context.Context, id *authn.Identity) bool {
return id.Subject == "admin" // true = allow, false = deny
}
The transport maps a false return to a generic 403 / PermissionDenied — the
predicate makes the decision; it does not shape the client-facing response.
Built-in combinators¶
Require scopes¶
RequireScopes
allows the request only if the identity carries all the named scopes (parsed from
the token's scope/scp claim into Identity.Scopes):
Require a claim¶
RequireClaim
allows the request only if a verified JWT claim equals an expected value:
Both return an AuthorizeFunc, so they drop straight into the same call site as a
hand-written predicate.
Using request metadata¶
An AuthorizeFunc can also see what is being accessed via
RequestMetadata
(the HTTP method + path, or grpc + the full method name). Your transport puts it on
the context; the predicate reads it:
ctx = authn.ContextWithRequestMetadata(ctx, authn.RequestMetadata{Method: "POST", Path: "/deploy"})
var authorize authn.AuthorizeFunc = func(ctx context.Context, id *authn.Identity) bool {
if md, ok := authn.RequestMetadataFromContext(ctx); ok && md.Method == "POST" {
// stricter rule for mutating requests
return authn.RequireScopes("deploy")(ctx, id)
}
return true
}
This keeps route-aware authorization in one predicate without teaching authn about
your routing table.
Putting it together¶
The end-to-end shape inside a middleware/interceptor is:
- Extract the credential from the transport.
Verifyit →Identity(else 401).authorize(ctx, id)→ allow or deny (else 403).ContextWithIdentity(ctx, id)and call the next handler.
Steps 2 and 3 are the whole of authn; steps 1 and 4 are transport glue you own.