Authentication Guide¶
Akashic MCP implements standard OAuth 2.0 and MCP token authentication. Only one of the following connection methods is required per request.
Official connection methods¶
| Method | Description |
|---|---|
| 1. MCP token | Send Authorization: Bearer <token> or use query ?token=<token>. Use an MCP token created in the dashboard or via the API. |
| 2. OAuth 2.0 (pre-registered client) | Create a client via the admin API or dashboard, then use the authorization code flow. Discovery: GET /.well-known/oauth-authorization-server. |
| 3. OAuth 2.0 + Dynamic Client Registration (RFC 7591) | Same OAuth flow; clients can register themselves at POST /oauth/register with redirect_uris and optional client_name, then use the authorization code flow. Optional; does not replace MCP token or pre-registered OAuth. |
Protected endpoints accept either an MCP token or an OAuth access token; you do not need both.
Overview¶
The authentication system supports:
- OAuth 2.0 Authorization Code Flow - Standard flow for web applications
- JWT Tokens - Secure access tokens
- Client Credentials - For server-to-server applications
- Multi-factor Authentication - MFA support via Firebase
OAuth 2.0 Endpoints¶
1. Authorization Endpoint¶
Initiates the authorization flow.
Endpoint: GET /oauth/authorize
Query Parameters:
- client_id (required): OAuth client ID
- redirect_uri (required): Redirect URI after authorization
- response_type (required): Must be "code"
- scope (optional): Requested scopes (space-separated)
- state (optional): State to prevent CSRF attacks
Example:
curl "https://akashic-mcp.com/oauth/authorize?client_id=my-client&redirect_uri=http://localhost:8080/callback&response_type=code&state=random-state"
2. Token Endpoint¶
Exchanges authorization code for access token.
Endpoint: POST /oauth/token
Content-Type: application/x-www-form-urlencoded
Parameters:
- grant_type (required): "authorization_code"
- code (required): Received authorization code
- redirect_uri (required): Same URI used in authorization
- client_id (required): Client ID
- client_secret (required): Client secret
Example:
curl -X POST https://akashic-mcp.com/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code&code=AUTH_CODE&redirect_uri=http://localhost:8080/callback&client_id=my-client&client_secret=my-secret"
Response:
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "refresh_token_here",
"scope": "read write"
}
3. Token Revocation¶
Revokes an access token.
Endpoint: POST /oauth/revoke
Parameters:
- token (required): Token to revoke
- token_type_hint (optional): "access_token" or "refresh_token"
Example:
curl -X POST https://akashic-mcp.com/oauth/revoke \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "token=ACCESS_TOKEN&token_type_hint=access_token"
4. Server Metadata¶
Gets OAuth server metadata (RFC8414). Served at the domain root so MCP clients such as ChatGPT can discover OAuth configuration when connecting to https://akashic-mcp.com/mcp.
Endpoint: GET /.well-known/oauth-authorization-server
Example:
OAuth Client Management¶
Create Client¶
Creates a new OAuth client (requires authentication).
Endpoint: POST /oauth/admin/clients
Authentication:
Protected endpoints accept authentication via:
- Authorization Header: Authorization: Bearer <token>
- Cookie: auth_token (set automatically after login)
- Query Parameter: ?token=<token>
Body:
{
"client_id": "my-client",
"client_secret": "my-secret",
"name": "My Application",
"redirect_uris": ["http://localhost:8080/callback"]
}
Example:
curl -X POST https://akashic-mcp.com/oauth/admin/clients \
-H "Authorization: Bearer YOUR_AUTH_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"client_id": "my-client",
"client_secret": "my-secret",
"name": "My Application",
"redirect_uris": ["http://localhost:8080/callback"]
}'
List Clients¶
Lists all user OAuth clients.
Endpoint: GET /oauth/admin/clients
Authentication:
Protected endpoints accept authentication via:
- Authorization Header: Authorization: Bearer <token>
- Cookie: auth_token (set automatically after login)
- Query Parameter: ?token=<token>
Regenerate Secret¶
Regenerates a client secret.
Endpoint: POST /oauth/admin/clients/:client_id/regenerate-secret
Authentication:
Protected endpoints accept authentication via:
- Authorization Header: Authorization: Bearer <token>
- Cookie: auth_token (set automatically after login)
- Query Parameter: ?token=<token>
Deactivate Client¶
Deactivates an OAuth client.
Endpoint: DELETE /oauth/admin/clients/:client_id
Authentication:
Protected endpoints accept authentication via:
- Authorization Header: Authorization: Bearer <token>
- Cookie: auth_token (set automatically after login)
- Query Parameter: ?token=<token>
Complete Authorization Flow¶
Step 1: Create OAuth Client¶
curl -X POST https://akashic-mcp.com/oauth/admin/clients \
-H "Authorization: Bearer YOUR_AUTH_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"client_id": "my-app",
"client_secret": "secure-secret",
"name": "My Application",
"redirect_uris": ["http://localhost:8080/callback"]
}'
Step 2: Redirect User¶
Redirect the user to the authorization endpoint:
https://akashic-mcp.com/oauth/authorize?client_id=my-app&redirect_uri=http://localhost:8080/callback&response_type=code&state=random-state
Step 3: User Authorizes¶
The user authorizes the application and is redirected to:
Step 4: Exchange Code for Token¶
curl -X POST https://akashic-mcp.com/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code&code=AUTHORIZATION_CODE&redirect_uri=http://localhost:8080/callback&client_id=my-app&client_secret=secure-secret"
Step 5: Use Token¶
Use the access token in requests:
Or using a cookie (if authenticated via browser):
Security¶
Best Practices¶
- Never expose client_secret in client code
- Use HTTPS in production
- Validate state to prevent CSRF
- Store tokens securely (cookies are automatically httpOnly and secure in production)
- Implement refresh tokens to renew expired tokens
- Use scopes to limit permissions
JWT Tokens¶
Access tokens are JWT (JSON Web Tokens) that include:
user_id: User IDexp: Expiration timeiat: Issued at timescope: Token scopes
Multi-Factor Authentication¶
The system supports MFA via Firebase. To enable it:
- Configure Firebase in the backend
- Enable MFA in Firebase Console
- Users can configure MFA in their profile
Troubleshooting¶
Error: "Invalid client"¶
- Verify that
client_idandclient_secretare correct - Make sure the client is active
Error: "Invalid redirect_uri"¶
- The
redirect_urimust match exactly with the registered one - Verify there are no spaces or special characters
Error: "Invalid authorization code"¶
- Authorization codes expire quickly (typically 10 minutes)
- Each code can only be used once
Cursor MCP: "Waiting for callback" disappears quickly¶
- The Cursor MCP client (anysphere.cursor-mcp) re-checks connection state about every second. On each poll it runs: ListOfferings, ListToolsRaw, GetInstructions; sees "No stored tokens"; then starts a new OAuth flow (new PKCE verifier, "Redirect to authorization requested", "OAuth provider needs auth callback"). That overwrites the previous "waiting for callback" state, so the window lasts ~1 second.
- This behavior is entirely on the client side; the server cannot extend the callback window. The MCP specification (Authorization) requires clients to start OAuth after receiving HTTP 401; it does not define how long the client should wait for the redirect callback. Cursor’s implementation does not keep a single pending OAuth session across polls.
- Workaround: When the "Authentication successful" page appears after signing in, click the "Open Cursor to complete login" link immediately. If you see "Needs authentication" again, click Connect in Cursor and then click the link on the success page right away.
- Reporting: Consider reporting to Cursor/Anysphere (e.g. forum, or MCP server auth code callback not launching cursor app) asking that the client keep one pending OAuth session until the callback is received or a longer timeout (e.g. 2–5 minutes) instead of re-initiating on every poll.
Additional Resources¶
- OAuth 2.0 Specification
- MCP Authorization (2025-03-26) — OAuth 2.1, 401 triggers client flow, PKCE required; redirect URIs must be localhost or HTTPS in the spec; Cursor uses
cursor://as an extension. - Cursor Changelog — MCP OAuth support
- Cursor Forum — MCP OAuth / callback issues
- Getting Started
- API Reference