Verify a delegation token
Verify the X-Omnia-Delegation header on a tool call with pkg/delegation, so
your handler knows which user and which agent the call was made for.
Prerequisites
Section titled “Prerequisites”- A tool backend registered as a handler in a
ToolRegistry, withdelegation.enabled: trueon that handler. See Opting in. - A route from your backend to the operator’s JWKS endpoint. Inside the
cluster that is the operator Service; outside it, enable
operator.delegationAPI.publicJWKSin the chart. See Verifying it for the URLs. - The handler’s audience,
<namespace>/<registry>/<handler>. For the handlerhttpin registryordersin namespaceacme, that isacme/orders/http.
-
Create one verifier when your service starts. It fetches the operator’s public keys on first use, caches them, and refetches only when a token names a key id it does not hold.
import ("github.com/go-logr/logr""github.com/altairalabs/omnia/pkg/delegation")// jwksURL and the audience are illustrative; use your own.var v = delegation.NewVerifier(jwksURL, "acme/orders/http", logr.Discard())The second argument is the audience from the prerequisites. The verifier rejects any token minted for a different one.
-
In the handler, verify the header before you trust anything in the request.
func handler(w http.ResponseWriter, r *http.Request) {claims, err := v.Verify(r.Context(), r.Header.Get(delegation.HeaderName))if err != nil {// No token, or one that cannot be judged. Refuse, or carry on// unattributed; the choice is yours.http.Error(w, "forbidden", http.StatusForbidden)return}agent := claims.Act.Sub // the agent, as the operator found ituser := claims.Subject // always present; check the origin firstif claims.UserIsVerified() {// origin is "oidc": the operator checked an identity provider itself.}} -
Decide what to do with an unverified user. Act on
claims.Subjectfor anything that spends a person’s credentials only whenclaims.UserIsVerified()is true. The other origins are listed in What is in the token.
Verify
Section titled “Verify”Call the tool through an agent whose handler has delegation.enabled: true.
Log claims.Subject and claims.Act.Sub in the handler and confirm both are
set for that call.
Then call your endpoint directly, without the header. Verify returns an
error, so the request takes your err != nil branch. A handler without
delegation.enabled behaves the same way, because the runtime sends no
header.
Troubleshooting
Section titled “Troubleshooting”Verify fails with an invalid audience
Section titled “Verify fails with an invalid audience”The audience you passed to NewVerifier differs from the handler’s
<namespace>/<registry>/<handler>. Your service cannot derive it, so check
the three names against the ToolRegistry.
Verify fails with an unknown key id or a JWKS fetch error
Section titled “Verify fails with an unknown key id or a JWKS fetch error”jwksURL is wrong or unreachable from your backend. Fetch it with curl from
the same place the backend runs. After a key rotation, the verifier refetches
on the next unrecognised key id, but no more often than every five seconds.
The tool call fails before it reaches your handler
Section titled “The tool call fails before it reaches your handler”The runtime could not obtain a token from the operator, and it fails the call rather than sending it without one. Check the agent’s runtime logs.
Related pages
Section titled “Related pages”- Delegation tokens: why a call carries this header, and what it does not guarantee
- Delegation tokens reference: claims, the opt-in field, and the verification rules for other languages
- Configure tool policies: decide what an authenticated caller may do