Manually authorize requests
When you deploy with the default web or slack adapter, the messaging sidecar handles authorization automatically: every incoming request is checked against the deployment’s grants table before it reaches your agent. If you’re running a frontend agent or a custom HTTP server inside the messaging container, there’s no sidecar to do this for you — but the platform still issues the same credentials, and you can call the same endpoint yourself.
This guide explains the contract and shows how to replicate it.
What the sidecar is doing
For every inbound request, the messaging sidecar:
- Extracts an identity from the request (the OIDC user_id for web, the Slack user/team for slack).
- Calls
GET /api/v1/deployments/authorizeon astro-server with that identity and the adapter name, authenticated by the deploy token. - Allows the request if the server returns
allowed: true; denies it otherwise. - Caches the answer for ~60s so chatty sessions don’t pay the round-trip on every event.
- Falls back to the deploy token’s
anyone_adaptersclaim if the server is unreachable, so an outage doesn’t take down open-grant deployments.
When you handle requests directly, you reproduce these five steps inside your agent.
Inputs the platform gives you
Every deployed agent — including frontend agents — receives a single environment variable:
The token is opaque to you, but two claims inside it are useful:
Decode the JWT once at startup to read iss. Don’t bother validating the signature — the server re-validates on every call.
The authorize call
Substitute the server URL with the iss claim from your ASTRO_AUTHZ_TOKEN, and pass the raw token as a Bearer credential:
Query parameters:
Response (200):
allowed— the final decision.user_id— the resolved platform user id when the server could resolve one (foridentity_type=userit’s the input echoed back; forslackit’s the linked platform user, empty when no mapping exists). Only present whenallowed: true.
Treat 4xx as malformed input (don’t retry) and 5xx as transient (retry once, then fail-closed).
Reference implementations
A minimal authorize client you can drop into your agent:
Node.js
Python
Source the identity from wherever your front door puts it — OIDC session cookie, signed header from a reverse proxy, custom JWT, etc. — and pass it to authorize() before serving the request.
Caveats worth knowing
- Cache for ~60s. Without a cache, every page navigation pays a round-trip to astro-server. The sidecar caches per
(identity_type, identity_id, adapter, identity_scope)for 60 seconds; do the same. Grant edits take up to a minute to propagate, which is acceptable. - Fail-closed on timeouts. A 5s timeout is the platform default. Treat any error as a denial unless the adapter is in the token’s
anyone_adaptersclaim — in which case a server outage should not lock everyone out of an open deployment. Cap the degraded-mode TTL low (10s or so) so recovery is reflected promptly. - Anonymous is only valid with an
anyonegrant. Sending emptyidentity_type+ emptyidentity_idis allowed by the server only when the adapter is publicly granted. If your UI has a public route, route it through the same authorize call with empty identity instead of branching around it. - Use the resolved
user_iddownstream. For Slack, the linked platform user id is what trace attribution and observability buckets are keyed on. For web, it’s just the input echoed back. Either way, forwardresult.user_idto your downstream telemetry rather than the raw input. - No token, no platform. In local dev (
ast project start),ASTRO_AUTHZ_TOKENis not set. Returnallowed: trueso devs aren’t blocked. The platform only injects the token in deployed builds.
When you don’t need this
If you’re using the default --adapter web flow, the sidecar already handles all of this for you and your agent code never sees ASTRO_AUTHZ_TOKEN directly. This guide is only relevant when:
- You set
agent.interfaces.frontend: trueand serve your own UI. - You’re authoring a custom adapter and want to wire authorize calls into the request path yourself.
- You’re building a server-to-server integration that talks to astro-server on the deployment’s behalf.