Authentication
Understanding how trame securely authenticates your MCP client
Overview
trame uses OAuth 2.1 Authorization Code Flow with PKCE (Proof Key for Code Exchange) for MCP client authentication. This industry-standard approach ensures secure token-based authentication while preventing common attack vectors like authorization code interception.
When you use trame through an MCP client, the OAuth flow happens automatically in the background. You only need to sign in through your web browser once, and your MCP client handles the rest.
How Authentication Works
The authentication process involves coordination between three components: your MCP client, your web browser, and the trame server. Here's what happens behind the scenes:
The OAuth Flow in Detail
Discovery
Your MCP client first discovers trame's OAuth capabilities by fetching well-known metadata endpoints. This tells it where to find authorization and token endpoints.
1# Protected Resource Metadata
2GET https://trame.sh/.well-known/oauth-protected-resource
3
4# Authorization Server Metadata
5GET https://trame.sh/.well-known/oauth-authorization-serverClient Registration
Your MCP client registers itself with trame using Dynamic Client Registration. It receives a unique client ID that identifies it in subsequent requests.
1POST https://trame.sh/oauth/register
2
3{
4 "client_name": "my-mcp-client",
5 "redirect_uris": ["http://localhost:8080/callback"]
6}
7
8// Response
9{
10 "client_id": "abc123...",
11 "client_name": "my-mcp-client",
12 "redirect_uris": ["http://localhost:8080/callback"]
13}Authorization Request
Your MCP client generates a PKCE code challenge and opens your browser to trame's authorization endpoint with all required parameters.
1GET https://trame.sh/oauth/authorize?
2 client_id=abc123&
3 redirect_uri=http://localhost:8080/callback&
4 response_type=code&
5 state=xyz789&
6 code_challenge=SHA256_HASH&
7 code_challenge_method=S256&
8 resource=https://trame.shThe resource parameter binds the resulting token to trame's MCP endpoint, preventing token reuse on other services.
User Authentication
trame redirects you to its web application where you authenticate using Firebase. You can sign in with:
- Google account (OAuth)
- Email and password
- Magic link (passwordless email)
After successful authentication, trame associates your Firebase user ID with the authorization code from the previous step.
Authorization Code Exchange
The browser redirects back to your MCP client with the authorization code. Your client then exchanges this code for an access token by proving it has the original PKCE code verifier.
1POST https://trame.sh/oauth/token
2
3{
4 "grant_type": "authorization_code",
5 "code": "auth_abc123",
6 "redirect_uri": "http://localhost:8080/callback",
7 "client_id": "abc123",
8 "code_verifier": "ORIGINAL_VERIFIER",
9 "resource": "https://trame.sh"
10}
11
12// Response
13{
14 "access_token": "eyJhbGciOiJSUzI1NiIs...",
15 "token_type": "Bearer",
16 "expires_in": 3600
17}trame validates the PKCE verifier, resource parameter, and all other security checks before issuing a Firebase ID token as the access token.
Authenticated MCP Requests
All future MCP requests from your client include the access token in the Authorization header. trame validates the token on every request.
1POST https://trame.sh/mcp
2Authorization: Bearer eyJhbGciOiJSUzI1NiIs...
3Content-Type: application/json
4
5{
6 "jsonrpc": "2.0",
7 "method": "tools/call",
8 "params": {"name": "whoami"},
9 "id": 1
10}Token Management
Access Tokens
Your access token is a Firebase ID token that expires after 1 hour. Your MCP client handles token refresh automatically - you won't notice when it happens.
Authorization Codes
Authorization codes are short-lived (60 seconds) and single-use. Once your MCP client exchanges a code for a token, that code becomes invalid and cannot be reused.
Token Storage
Your MCP client stores your access token securely on your local machine. It never leaves your device except when sent to trame in API requests.
Security Features
OAuth 2.1 Compliance
Implements the latest OAuth 2.1 draft specification with mandatory PKCE and modern security best practices.
Audience Binding (RFC 8707)
Tokens are cryptographically bound to trame's MCP endpoint, preventing token reuse attacks even if tokens are compromised.
PKCE (S256 Required)
Prevents authorization code interception by requiring proof of the original secret that generated the code challenge.
Single-Use Authorization Codes
Each authorization code can only be exchanged once and expires after 60 seconds, limiting the window for potential attacks.
Firebase Token Validation
Every request validates the Firebase ID token signature, expiry, and audience claim before processing.
Troubleshooting
Authentication window doesn't open
- Check if your browser is blocking popups from your MCP client
- Verify you have an active internet connection
- Try manually opening the URL that your MCP client displays
- Ensure your firewall isn't blocking the OAuth redirect
OAuth flow completes but authentication fails
- Verify the authorization code hasn't expired (60 second limit)
- Check that you completed all steps without closing the browser
- Ensure you clicked the final authorization button in the browser
- Try the entire flow again from the beginning
Token expired errors
- Your MCP client should refresh tokens automatically
- Try disconnecting and reconnecting the MCP server
- If issues persist, clear stored tokens and re-authenticate
- Check your MCP client's logs for refresh token errors
Invalid audience errors
- Verify the URL in your MCP client config matches the server
- For local dev, ensure you're using
http://localhost:3001/mcp - For production, use
https://trame.sh/mcp - Re-authenticate after changing the URL
Firebase authentication issues
- Try a different sign-in method (Google vs email)
- Check if your email provider is blocking Firebase emails
- Verify your Google account isn't restricted
- Clear browser cookies for trame.sh and try again
Advanced Topics
Local Development
When running trame locally, the authentication flow uses Firebase emulator instead of production Firebase:
1# Start Firebase emulator
2just start-emulator
3
4# Configure for local development
5# In docker-compose.env.yml:
6USE_FIREBASE_EMULATOR=true
7FIREBASE_PROJECT_ID=demo-trame
8FIREBASE_AUTH_EMULATOR_HOST=firebase-emulator:9099Use http://localhost:3001/mcp in your MCP client config when developing locally.
Token Inspection
Firebase ID tokens are JWTs (JSON Web Tokens). You can decode them to inspect claims and expiry:
1# Decode JWT (header.payload.signature)
2echo "eyJhbGciOiJSUzI1NiIs..." | cut -d. -f2 | base64 -d | jq
3
4# Typical claims:
5{
6 "iss": "https://securetoken.google.com/project-id",
7 "aud": "https://trame.sh/mcp",
8 "auth_time": 1234567890,
9 "user_id": "firebase_uid_123",
10 "sub": "firebase_uid_123",
11 "iat": 1234567890,
12 "exp": 1234571490
13}Revoking Access
To revoke your MCP client's access to your trame account:
- Sign out from your Firebase account
- Clear stored tokens in your MCP client
- Disconnect the trame MCP server from your MCP client
- Optionally, delete your trame account from the web dashboard