Authentication Guide

This guide explains how to secure your Strava MCP server with OAuth (Claude Web/Mobile) and Bearer token authentication (desktop clients).

Overview

The Lambda function supports two authentication modes:

  1. OAuth 2.1 (Claude Web/Mobile) via Dynamic Client Registration and the authorization code flow.
  2. Bearer token authentication for Claude Desktop and other MCP clients that support custom headers.

Bearer token authentication provides:

  • ✅ Simple, effective security without complex AWS services
  • ✅ 100% free (no additional costs)
  • ✅ Works with Claude Desktop and other MCP clients that support headers
  • ✅ Easy to rotate tokens when needed

Authentication Modes

The server supports two authentication modes:

1. Bearer Token Authentication (Default for /mcp endpoint)

For Claude Desktop and other MCP clients that support custom headers.

┌──────────────┐
│ Claude Client│
└──────┬───────┘
       │ Authorization: Bearer <token>
       ▼
┌──────────────┐
│   Lambda     │─── Validates token
│  (Middleware)│
└──────┬───────┘
       │ If valid, proceed
       ▼
┌──────────────┐
│  MCP Server  │
│ (Strava API) │
└──────────────┘

OAuth (Claude Web/Mobile)

Claude Web connects using OAuth:

  1. Metadata discovery at /.well-known/oauth-authorization-server
  2. Dynamic client registration at /register
  3. Authorization code + PKCE flow via /authorize and /token

Setup Steps

1. Deploy and Auto-Generate AUTH_TOKEN

The deployment script automatically generates a secure AUTH_TOKEN for you:

bun run deploy

This will:

  • Generate a secure 64-character random token
  • Store it in samconfig.toml (gitignored for security)
  • Deploy your Lambda function with authentication enabled
  • Display your complete MCP configuration

View your configuration anytime:

bun run deploy:show-config

This displays:

  • Complete Claude Desktop JSON configuration
  • Claude Web/Mobile OAuth base URL
  • Your AUTH_TOKEN (for desktop clients)
  • Health check test command

2. Deploy with Authentication

Option A: Interactive Deployment (guided prompts)

bun run deploy

When prompted for AuthToken, paste the token generated in step 1.

Option B: Command Line (specify token directly)

# Generate token first
TOKEN=$(node -e "console.log(require('crypto').randomBytes(32).toString('hex'))")

# Deploy with token
sam deploy --parameter-overrides \
  StravaClientId=YOUR_CLIENT_ID \
  StravaClientSecret=YOUR_SECRET \
  StravaRefreshToken=YOUR_REFRESH_TOKEN \
  AuthToken=$TOKEN

Option C: Update Existing Deployment

Add to your samconfig.toml:

[default.deploy.parameters]
parameter_overrides = [
  "StravaClientId=xxx",
  "StravaClientSecret=xxx", 
  "StravaRefreshToken=xxx",
  "AuthToken=your-token-here"
]

3. Configure Your MCP Client

After deployment, get your Function URL from the deployment output.

Claude Desktop (Bearer Token)

Add as a Custom Connector in Claude Settings:

{
  "name": "strava",
  "url": "https://your-function-url.lambda-url.us-east-1.on.aws/mcp",
  "headers": {
    "Authorization": "Bearer your-auth-token-here"
  }
}

Important: The URL must end with /mcp - this is the MCP endpoint.

Claude Web/Mobile (OAuth)

Settings → Connectors → Add custom connector:

  • URL: https://your-function-url.lambda-url.us-east-1.on.aws (base URL only)
  • Claude will complete OAuth automatically

4. Test Authentication

Test that authentication is working:

FUNCTION_URL="https://your-function-url.lambda-url.us-east-1.on.aws/"
AUTH_TOKEN="your-token-here"

# Without token - should return 401
curl $FUNCTION_URL

# With valid token - should return {"status":"healthy"}
curl -H "Authorization: Bearer $AUTH_TOKEN" ${FUNCTION_URL}health

Token Management

Rotating Your Token

To rotate your authentication token:

  1. Generate new token manually:
    # Generate a secure random token
    node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
    
  2. Update samconfig.toml with the new token in the parameter_overrides section, or update directly during deployment:
    sam deploy --parameter-overrides AuthToken=NEW_TOKEN
    
  3. View updated configuration:
    bun run deploy:show-config
    
  4. Update all MCP clients with the new token

  5. Restart Claude (Desktop) or refresh (Web/Mobile)

Token Best Practices

DO:

  • Use the generated 64-character tokens (high entropy)
  • Store tokens in password managers
  • Rotate tokens periodically (every 3-6 months)
  • Use different tokens for different environments

DON’T:

  • Commit tokens to version control
  • Share tokens publicly
  • Use short or predictable tokens
  • Reuse tokens across multiple services

Authless Mode Configuration

Enabling Authless Mode (Default)

Authless mode is enabled by default for Claude.ai compatibility. The ALLOW_AUTHLESS parameter is set to "true" in the SAM template.

When enabled:

  • SSE endpoints (/sse, /sse/, /message) do not require authentication
  • The /mcp JSON-RPC endpoint still requires Bearer token authentication
  • Claude.ai custom connectors can connect using the base URL

Disabling Authless Mode

To require Bearer token authentication for all endpoints:

# During deployment
sam deploy --parameter-overrides AllowAuthless=false

# Or update samconfig.toml
[default.deploy.parameters]
parameter_overrides = [
  "AllowAuthless=false",
  # ... other parameters
]

When disabled:

  • All endpoints require Bearer token authentication
  • Claude.ai custom connectors will NOT work (they cannot send custom headers)
  • Only Claude Desktop and clients supporting custom headers can connect

Security Implications

Authless mode enabled (ALLOW_AUTHLESS=true, advanced / opt-in):

  • ⚠️ Not enabled by default. Enabling this on a publicly accessible Lambda URL exposes /sse, /sse/, and /message without authentication.
  • ⚠️ Anyone who learns your Lambda URL (via logs, screenshots, or misconfiguration) can access your Strava-backed tools via SSE; URL secrecy alone is not sufficient protection.
  • ✅ Only enable for strictly local or personal use where you fully control access to the URL.
  • 💡 If you must use authless mode in a cloud environment, combine it with additional controls such as AWS WAF/IP allowlisting and/or an extra shared secret (e.g., a query parameter or header checked by your Lambda).

Authless mode disabled (ALLOW_AUTHLESS=false, recommended default):

  • ✅ All requests require a valid Bearer token
  • ❌ Claude.ai custom connectors won’t work
  • ✅ Maximum security for shared, team, or production environments

Security Considerations

What This Protects

✅ Prevents unauthorized access to your Strava data ✅ Stops random internet users from using your Lambda function ✅ Protects against API abuse and unexpected costs ✅ Simple to implement and maintain

What This Doesn’t Protect

⚠️ Not protection against:

  • MITM attacks (use HTTPS, which Lambda provides)
  • Token leakage from client-side code
  • Compromised client devices
  • AWS account breaches

Production Hardening

For production deployments, consider:

  1. API Gateway + WAF
    • Add AWS WAF for DDoS protection
    • Implement rate limiting per token
    • Add geographic restrictions
  2. Token Rotation
    • Implement automatic token rotation
    • Use AWS Secrets Manager
    • Expire tokens after fixed period
  3. Monitoring
    • Enable CloudWatch logging
    • Alert on authentication failures
    • Track token usage patterns
  4. Additional Security Layers
    • Add request signing (AWS SigV4)
    • Implement IP allowlisting
    • Use AWS API Gateway with API keys

Troubleshooting

“401 Unauthorized” Error

Symptoms: MCP client shows “Unauthorized” or “Invalid token”

Solutions:

  1. Verify token in MCP config matches deployed token
  2. Check for extra spaces or quotes in token
  3. Ensure Authorization: Bearer prefix is correct (note the space)
  4. Restart Claude after config changes

Health Check Returns 401

Symptoms: /health endpoint requires authentication

Solution: Health check should NOT require auth. Check if middleware is correctly bypassing /health path.

Token Not Working After Deployment

Symptoms: Token worked during deployment but fails in use

Solutions:

  1. Verify Lambda environment variable is set:
    aws lambda get-function-configuration \
      --function-name strava-mcp-server \
      --query 'Environment.Variables.AUTH_TOKEN'
    
  2. Check CloudWatch logs for auth errors
  3. Redeploy with explicit token parameter

Multiple Clients Need Access

Solution:

  • Use same token for all your devices/clients
  • OR deploy separate Lambda functions with different tokens
  • OR implement token-per-client logic (custom development)

Migration from No Auth

If you’re upgrading from an unauthenticated deployment:

  1. Generate token: node generate-mcp-config.js
  2. Update deployment: sam deploy --parameter-overrides AuthToken=NEW_TOKEN
  3. Update all MCP clients with new headers
  4. Test before removing old deployment

The Lambda function will immediately start requiring authentication after deployment.

Cost Impact

None! Bearer token authentication:

  • Runs in your application code (no extra AWS services)
  • No additional API Gateway costs
  • No Cognito costs
  • Still 100% free with AWS Free Tier

Further Reading