🚧 Roadmap — The capability described here is on the roadmap. The concepts and design are settled; interfaces and steps are subject to the final release.
Protect your APIs: resource-side integration
Everything up to here has been about handing authority to an agent safely. This page is about the last hop, and the one most often overlooked: the token arrives at your API — now what do you check?
Get this hop wrong and every bit of attenuation, approval and audit upstream stops meaning anything, because the party that ultimately decides "allow or deny" is your resource service, not the issuer.
By the end of this guide you will know:
- The five-step checklist, and what slips through if you skip a step
- Why you must check
act.typeexplicitly instead of parsing the RFC 8693 standard shape - How to make your business logs the final link of the audit chain
Prerequisites
- You understand the access token's field structure (see Token and claim reference)
- Your API already validates JWTs (signature, expiry)
The five-step checklist
| Step | What to check | What slips through if you skip it |
|---|---|---|
| 1 | Signature and expiry | Forged or expired tokens are accepted |
| 2 | aud is your resource | A token minted for another resource works against your API (audience confusion) |
| 3 | Read sub for business authorization | The agent becomes a superuser, bypassing your existing data permissions |
| 4 | Read act to identify the actor, and log it | The audit trail cannot separate "the user in person" from "an agent acting for them" — no accountability |
| 5 | Verify the scope covers this operation | A read-only grant is used to write — attenuation is dead |
Step 3 is the mistake teams make most
Many integrations treat "the token is valid" as "this operation is allowed", so an agent holding a read-only token sails straight through a write endpoint — because the business authorization layer got skipped.
Do it this way: feed sub into your existing authorization logic as the acting principal. The upper bound on an agent's authority is the delegator's own authority; not one of your existing data permission rules can be dropped. Scope is an additional narrowing, not a replacement.
Pseudocode
async function authorizeAgentRequest(req: Request, requiredScope: string) {
const token = readBearer(req);
// (1) Signature and expiry (use your existing JWT library)
const claims = await verifyJwt(token);
// (2) The audience must be your resource
if (!audienceMatches(claims.aud, MY_RESOURCE_ID)) {
throw forbidden("audience_mismatch");
}
// (3) sub is the person being represented — feed it into your existing business authorization
const actingFor = claims.sub;
await assertBusinessPermission(actingFor, req.action, req.resource);
// (4) act identifies the actual actor
// Note: GenAuth's act is an extension object with a type discriminator,
// not the RFC 8693 nested-sub shape — you must check type explicitly
let agentId: string | null = null;
if (claims.act && claims.act.type === "eak_delegation") {
agentId = claims.act.agent_id;
}
// When act is missing or type does not match: decide by policy whether to reject
// or treat it as a non-agent call. For agent-only endpoints, fail closed (reject)
// so a structural change cannot silently skip this check.
// (5) The scope must cover this operation
const scopes = normalizeScopes(claims.scope);
if (!scopes.includes(requiredScope)) {
throw forbidden("insufficient_scope");
}
// The audit seam: these three fields extend the chain from GenAuth into your business logs
logger.info("agent_request", {
sub: actingFor,
agent_id: agentId,
audit_id: claims.audit_id,
grant_id: claims.grant_id,
action: req.action,
});
return { actingFor, agentId };
}Why act needs special handling
RFC 8693 defines act as a nested sub ({"act": {"sub": "..."}}); GenAuth's act is {"type": "eak_delegation", "agent_id", "grant_id", "access_key_id"}. If you point an off-the-shelf RFC 8693 parser at it, you get nothing back and no error — which is the most dangerous outcome: validation appears to pass while checking nothing. Explicitly checking type is the only safe approach.
Keep an emergency cut-off
A delegate token already issued cannot be invalidated individually within its lifetime (see Revocation and incident response). So build a deny list capability on the resource side:
- Reject by
act.agent_id: when one agent misbehaves, cut all of its access to your API in one move - Reject by
grant_id: when one grant is judged mistaken, cut exactly that one
The implementation can be trivial — a hot-reloadable config or a Redis set, checked right after step (4). You will not use it most days; during an incident it is your only way to cut off a token inside its lifetime.
The gateway option
If your architecture has a unified API gateway, putting these five checks at the gateway beats putting them in every service:
- Validation logic maintained in one place; new services onboard for free
- The deny list takes effect at the gateway, so containment is faster
- The gateway passes
sub/agent_id/audit_iddown to services (for example as internal headers) and services stay focused on business logic
A gateway plugin is on the roadmap; until then, your gateway's generic JWT or scripting capability implements the logic above.
FAQ
My API already supports OAuth — do I need to change anything? What changes is the meaning of steps (3), (4) and (5): sub used to be the caller; now sub is the person being represented and act is the caller. Authorize on sub, log on act.
Do scope names have to map one-to-one onto my endpoints? Not one-to-one, but they must map. Design them as "resource + action" (for example orders:read) and declare the required scope at the endpoint layer instead of scattering checks through your code.
Can I trust GenAuth's validation and skip mine? No. The issuer can only guarantee "I minted this token and it has not been tampered with". Only you know which record this request touches. Resource-side validation cannot be outsourced.
Next steps
- Token and claim reference — the authoritative field definitions.
- Revocation and incident response — where the deny list sits in the incident flow.
- Security considerations — the full analysis of audience confusion and token passthrough.