Skip to main content

Authentication mechanisms

Albus supports four mechanisms for authenticating requests from the Albus platform to your hosted MCP servers: The default example below provides the complete agent configuration and run request. Each alternative shows a diff against the default MCP server entry; apply only the diff for the mechanism your server requires.

1. Albus identity JWT (default)

Use the default mechanism to authenticate Albus without provisioning a shared secret or registering Albus as a client with your identity provider. A server entry with no auth field defaults to "auth": {"type": "albus_identity_jwt"}: every request to the server includes the header Authorization: Bearer <token>, where <token> is an identity token minted by Albus for your organization and the declared server URL. Authenticate the CLI or SDK with ALBUS_API_KEY as described in Authentication. Replace the example MCP URL with your server’s Streamable HTTP endpoint.
Configure your server or gateway to verify the signature, expiry, issuer, and audience of every identity token: Discovery is available at <issuer>/.well-known/openid-configuration.
The identity token is an ES256 JWT with exactly the following six claims:
The issuer serves the standard discovery documents, public and cached for one hour:
  • <issuer>/.well-known/openid-configuration
  • <issuer>/.well-known/jwks.json
withMcpAuth from mcp-handler calls your verifier function with the bearer token and answers 401 when the verifier function returns undefined. Verify the token with jose:
app/api/mcp/route.ts
jwtVerify checks the signature against the JWKS and validates the exp, iss, and aud claims. Tool handlers read the session id and invocation id from ctx.http?.authInfo.extra.
oidc.NewProvider reads the discovery document from the issuer; the ClientID field of oidc.Config is the expected audience.
If your server is used by more than one Albus organization, keep an allowlist of the issuers you trust and configure a verifier for each issuer. Select the verifier by the token’s iss claim only when the iss value is in the allowlist. Never fetch a JWKS from an issuer you did not configure: whoever controls the iss value would then control the signing key.Signing keys rotate by kid. Configure the verifier to select the key by kid and refetch the JWKS when a token contains an unknown kid. New keys are published before use; old keys remain published until tokens signed with the old keys have expired. Do not pin a key or cache the JWKS beyond the response’s cache headers.

2. OAuth 2.0 client credentials

If your server already requires tokens from Auth0, Okta, WorkOS, or another OAuth 2.0 provider, use oauth2_client_credentials to keep the server’s existing verification. Albus calls token_url with the client credentials when the run starts and sends the returned access token as Authorization: Bearer <access-token>. Store the client secret as an Albus secret first (client_id may be a secret reference or a literal):
Albus obtains the access token once, at launch, and does not refresh the access token during the run. The access token must be valid for at least 10 minutes or the launch fails. If the access token expires during a long run, every 401 from the server appears in the audit log as mcp_auth_rejected and as a tool error visible to the model.

3. Static bearer token

Use bearer when your server accepts a fixed access token and does not need an identity provider exchange. Albus resolves the secret at launch and sends Authorization: Bearer <secret> on every MCP request. Store the token without the Bearer prefix:
auth.token must be a secret reference; a raw token is rejected.

4. Custom headers

Use headers when your server requires an API key in a custom header, another authorization scheme, or a token the caller obtains before the run. Header values can be secret references or literals. For an X-API-Key header, store the key as a secret:
Headers other than Authorization combine with any auth mode. An Authorization entry in headers (in any casing) disables the default identity token and is sent verbatim, so the value must be the complete header value, scheme included (Bearer <token> or token <token>). A request with both an explicit auth block and a headers.Authorization entry is rejected with 400.

Caller-minted tokens

If your application already holds credentials for the server’s identity provider, mint a short-lived access token before calling run_session and pass the access token as a literal headers.Authorization value. Your server keeps trusting the same provider, and the provider credentials stay with your application. With the minted access token in MCP_ACCESS_TOKEN, apply this change to the default example before submitting the run. The CLI command uses jq to add the header to the complete agent configuration.
Albus sends the header value unchanged and does not refresh the access token. Mint a token whose lifetime exceeds the run. A literal header value is not stored: the agent revision records the header name with the value "<literal>", so a token minted per run does not create a new revision, and a retry with the same idempotency key and a freshly minted token re-attaches to the original run.

Vercel Deployment Protection

Store the deployment bypass secret with Albus and use the header x-vercel-protection-bypass with a value such as albus.sh/secrets/acme-vercel-bypass. The bypass header lets the request reach your handler; the handler still verifies the identity token to authorize the request. Leave auth at its default to use both checks. For 401 responses recorded as mcp_auth_rejected, check the issuer and audience, the complete Authorization value, and the token’s expiry. See Troubleshooting.