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:
- OAuth 2.1 (Claude Web/Mobile) via Dynamic Client Registration and the authorization code flow.
- 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:
- Metadata discovery at
/.well-known/oauth-authorization-server - Dynamic client registration at
/register - Authorization code + PKCE flow via
/authorizeand/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:
- Generate new token manually:
# Generate a secure random token node -e "console.log(require('crypto').randomBytes(32).toString('hex'))" - Update samconfig.toml with the new token in the
parameter_overridessection, or update directly during deployment:sam deploy --parameter-overrides AuthToken=NEW_TOKEN - View updated configuration:
bun run deploy:show-config -
Update all MCP clients with the new token
- 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
/mcpJSON-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/messagewithout 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:
- API Gateway + WAF
- Add AWS WAF for DDoS protection
- Implement rate limiting per token
- Add geographic restrictions
- Token Rotation
- Implement automatic token rotation
- Use AWS Secrets Manager
- Expire tokens after fixed period
- Monitoring
- Enable CloudWatch logging
- Alert on authentication failures
- Track token usage patterns
- 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:
- Verify token in MCP config matches deployed token
- Check for extra spaces or quotes in token
- Ensure
Authorization: Bearerprefix is correct (note the space) - 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:
- Verify Lambda environment variable is set:
aws lambda get-function-configuration \ --function-name strava-mcp-server \ --query 'Environment.Variables.AUTH_TOKEN' - Check CloudWatch logs for auth errors
- 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:
- Generate token:
node generate-mcp-config.js - Update deployment:
sam deploy --parameter-overrides AuthToken=NEW_TOKEN - Update all MCP clients with new headers
- 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