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:

1.Your MCP client discovers OAuth endpoints from trame
2.Client registers with trame and receives a client ID
3.MCP client generates PKCE challenge (security measure)
4.Your browser opens to trame's login page
5.You sign in with Google or email via Firebase
6.trame associates your Firebase account with authorization code
7.Browser redirects back to MCP client with auth code
8.MCP client exchanges auth code for access token
9.All subsequent MCP requests include the access token
What is PKCE?
PKCE (Proof Key for Code Exchange) is a security extension that prevents authorization code interception attacks. Your MCP client generates a random secret (code verifier), sends a hash of it during authorization, and proves it knows the original secret when exchanging the code for a token. This ensures even if an attacker intercepts the authorization code, they can't use it without the original secret.

The OAuth Flow in Detail

1

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-server
2

Client 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}
3

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.sh

The resource parameter binds the resulting token to trame's MCP endpoint, preventing token reuse on other services.

4

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.

5

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.

6

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.

Tokens are bound to trame's MCP endpoint through the audience claim. They can't be used to access other services, even if intercepted.

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
Still having issues?
If authentication continues to fail after trying these steps, check the MCP server logs for detailed error messages. For local development, ensure Firebase emulator is running. For production issues, verify the trame service is operational.

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:9099

Use 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:

  1. Sign out from your Firebase account
  2. Clear stored tokens in your MCP client
  3. Disconnect the trame MCP server from your MCP client
  4. Optionally, delete your trame account from the web dashboard
Next steps: Now that you understand authentication, you're ready to create your first project. Check out the First Project tutorial to get started with trame's features.