Authentication¶
The IO Aerospace MCP Server is a protected resource under the MCP authorization specification, implemented with OAuth 2.1 + PKCE on top of WorkOS AuthKit. Two independent checks gate every tool call:
- Authentication — the request must carry a valid JWT bearer token issued by the WorkOS authorization server
- Active license — the email in the token must resolve to an active license on the IO Aerospace license server
Both checks run on the /mcp route. The discovery and health endpoints (/.well-known/oauth-protected-resource, /.well-known/oauth-protected-resource/mcp, /healthz) are anonymous.
How a client signs in¶
Modern MCP clients implement the discovery flow described in RFC 9728 and the MCP authorization spec. You do not paste an API key. The first time a client talks to the server it walks through these steps automatically:
client mcp.io-aerospace.org
│ POST /mcp (no Authorization) │
│ ────────────────────────────────────────► │
│ 401 Unauthorized │
│ WWW-Authenticate: Bearer │
│ resource_metadata="…/oauth-protected-…" │
│ ◄──────────────────────────────────────── │
│ │
│ GET /.well-known/oauth-protected-resource… │
│ ────────────────────────────────────────► │
│ { resource, authorization_servers: [..], │
│ bearer_methods_supported, scopes_… } │
│ ◄──────────────────────────────────────── │
│ │
│ …OAuth 2.1 + PKCE against WorkOS, │
│ resource="https://…/mcp" │
│ │
│ POST /mcp (Authorization: Bearer …) │
│ ────────────────────────────────────────► │
│ 200 OK + MCP response │
│ ◄──────────────────────────────────────── │
The browser opens once, you sign in with WorkOS, and the client stores the access token (typically refreshable).
Discovery metadata¶
Anyone can fetch the protected-resource metadata document:
{
"resource": "https://mcp.io-aerospace.org/mcp",
"authorization_servers": ["https://<workos-issuer>/"],
"bearer_methods_supported": ["header"],
"scopes_supported": ["openid", "email", "offline_access"]
}
The same document is served at the bare path /.well-known/oauth-protected-resource, because clients differ on which they probe.
The resource value is the exact RFC 8707 resource indicator clients must use when requesting tokens, and the value the server's audience check compares against. It always includes the /mcp path; a bare-origin resource indicator is ambiguous about the trailing slash and is rejected.
Token requirements¶
The server validates incoming JWTs with the following rules:
| Field | Expectation |
|---|---|
| Signature | Verified against the WorkOS JWKS, discovered from the RFC 8414 authorization-server metadata at <issuer>/.well-known/oauth-authorization-server |
iss (issuer) |
Must match the configured WorkOS issuer |
aud (audience) |
Must equal https://mcp.io-aerospace.org/mcp (the canonical MCP endpoint URL). The slash/no-slash variants of that exact string are also accepted defensively. |
sub (subject) |
Must be present |
exp |
Must not be in the past |
If validation fails the server returns 401 Unauthorized with the same WWW-Authenticate: Bearer resource_metadata="…" header so a well-behaved client re-runs discovery and refreshes the token.
WorkOS Resource Indicator setup
WorkOS access tokens only carry an aud claim when the MCP server is registered as a Resource Indicator in the WorkOS dashboard. The hosted instance is already configured this way.
Active-license check¶
A valid JWT proves you signed in. It does not prove you are entitled to use the service.
After the bearer token is validated, an authorization handler (LicenseAuthorizationHandler) calls the IO Aerospace license server to check that the sub and email in the token correspond to an active license. The request is HMAC-signed with a shared secret so the license server can trust it.
If the license check fails the request is rejected (typically 403 Forbidden). The token may be perfectly valid; you still need a license.
License-check results are cached in memory for a short interval to avoid hammering the license server on every tool call.
Obtaining a license¶
Licenses are issued by IO Aerospace and bound to the email you sign in with at WorkOS. Contact IO Aerospace to request access.
If you have signed in successfully but tool calls fail with a 403 / license error, your sign-in is fine but the license is missing or expired.
Scopes¶
Only standard OpenID Connect scopes are requested:
openid— required, identifies the useremail— used to match against the license serveroffline_access— lets the client refresh the access token without re-prompting
No custom scopes are needed. There is no per-tool authorization; if the license check passes, every tool in the catalog is callable.
Anonymous endpoints¶
For completeness, the following endpoints do not require a token:
| Path | Purpose |
|---|---|
GET /healthz |
Liveness probe (returns 200) |
GET /.well-known/oauth-protected-resource |
RFC 9728 metadata (bare path) |
GET /.well-known/oauth-protected-resource/mcp |
RFC 9728 metadata (path-specific) |
Everything under /mcp (including /mcp/sse) requires authentication and an active license.
Troubleshooting¶
| Symptom | Likely cause |
|---|---|
Client prints McpAuthorizationError and never opens a browser |
Client URL is https://mcp.io-aerospace.org instead of https://mcp.io-aerospace.org/mcp. The trailing-slash-on-bare-origin ambiguity breaks discovery. Use the /mcp URL. |
401 Unauthorized after sign-in |
Audience mismatch. The token's aud is not https://mcp.io-aerospace.org/mcp. Re-run discovery; clear cached tokens. |
403 Forbidden after sign-in |
License check failed. The email in the token has no active license. |
Token validation works but later requests start failing with 401 |
Access token expired. The client should be using offline_access to refresh it transparently. |
See also Guides → Troubleshooting.