|
| 1 | +--- |
| 2 | +title: AWS Cognito OAuth 🤝 FastMCP |
| 3 | +sidebarTitle: AWS Cognito |
| 4 | +description: Secure your FastMCP server with AWS Cognito user pools |
| 5 | +icon: aws |
| 6 | +tag: NEW |
| 7 | +--- |
| 8 | + |
| 9 | +import { VersionBadge } from "/snippets/version-badge.mdx" |
| 10 | + |
| 11 | +<VersionBadge version="2.12.4" /> |
| 12 | + |
| 13 | +This guide shows you how to secure your FastMCP server using **AWS Cognito user pools**. Since AWS Cognito doesn't support Dynamic Client Registration, this integration uses the [**OAuth Proxy**](/servers/auth/oauth-proxy) pattern to bridge AWS Cognito's traditional OAuth with MCP's authentication requirements. It also includes robust JWT token validation, ensuring enterprise-grade authentication. |
| 14 | + |
| 15 | +## Configuration |
| 16 | + |
| 17 | +### Prerequisites |
| 18 | + |
| 19 | +Before you begin, you will need: |
| 20 | +1. An **[AWS Account](https://aws.amazon.com/)** with access to create AWS Cognito user pools |
| 21 | +2. Basic familiarity with AWS Cognito concepts (user pools, app clients) |
| 22 | +3. Your FastMCP server's URL (can be localhost for development, e.g., `http://localhost:8000`) |
| 23 | + |
| 24 | +### Step 1: Create an AWS Cognito User Pool and App Client |
| 25 | + |
| 26 | +Set up AWS Cognito user pool with an app client to get the credentials needed for authentication: |
| 27 | + |
| 28 | +<Steps> |
| 29 | +<Step title="Navigate to AWS Cognito"> |
| 30 | + Go to the **[AWS Cognito Console](https://console.aws.amazon.com/cognito/)** and ensure you're in your desired AWS region. |
| 31 | + |
| 32 | + Select **"User pools"** from the side navigation (click on the hamburger icon at the top left in case you don't see any), and click **"Create user pool"** to create a new user pool. |
| 33 | +</Step> |
| 34 | + |
| 35 | +<Step title="Define Your Application"> |
| 36 | + AWS Cognito now provides a streamlined setup experience: |
| 37 | + |
| 38 | + 1. **Application type**: Select **"Traditional web application"** (this is the correct choice for FastMCP server-side authentication) |
| 39 | + 2. **Name your application**: Enter a descriptive name (e.g., `FastMCP Server`) |
| 40 | + |
| 41 | + The traditional web application type automatically configures: |
| 42 | + - Server-side authentication with client secrets |
| 43 | + - Authorization code grant flow |
| 44 | + - Appropriate security settings for confidential clients |
| 45 | + |
| 46 | + <Info> |
| 47 | + Choose "Traditional web application" rather than SPA, Mobile app, or Machine-to-machine options. This ensures proper OAuth 2.0 configuration for FastMCP. |
| 48 | + </Info> |
| 49 | +</Step> |
| 50 | + |
| 51 | +<Step title="Configure Options"> |
| 52 | + AWS will guide you through configuration options: |
| 53 | + |
| 54 | + - **Sign-in identifiers**: Choose how users will sign in (email, username, or phone) |
| 55 | + - **Required attributes**: Select any additional user information you need |
| 56 | + - **Return URL**: Add your callback URL (e.g., `http://localhost:8000/auth/callback` for development) |
| 57 | + |
| 58 | + <Tip> |
| 59 | + The simplified interface handles most OAuth security settings automatically based on your application type selection. |
| 60 | + </Tip> |
| 61 | +</Step> |
| 62 | + |
| 63 | +<Step title="Review and Create"> |
| 64 | + Review your configuration and click **"Create user pool"**. |
| 65 | + |
| 66 | + After creation, you'll see your user pool details. Save these important values: |
| 67 | + - **User pool ID** (format: `eu-central-1_XXXXXXXXX`) |
| 68 | + - **Client ID** (found under → "Applications" → "App clients" in the side navigation → \<Your application name, e.g., `FastMCP Server`\> → "App client information") |
| 69 | + - **Client Secret** (found under → "Applications" → "App clients" in the side navigation → \<Your application name, e.g., `FastMCP Server`\> → "App client information") |
| 70 | + |
| 71 | + <Tip> |
| 72 | + The user pool ID and app client credentials are all you need for FastMCP configuration. |
| 73 | + </Tip> |
| 74 | +</Step> |
| 75 | + |
| 76 | +<Step title="Configure OAuth Settings"> |
| 77 | + Under "Login pages" in your app client's settings, you can double check and adjust the OAuth configuration: |
| 78 | + |
| 79 | + - **Allowed callback URLs**: Add your server URL + `/auth/callback` (e.g., `http://localhost:8000/auth/callback`) |
| 80 | + - **Allowed sign-out URLs**: Optional, for logout functionality |
| 81 | + - **OAuth 2.0 grant types**: Ensure "Authorization code grant" is selected |
| 82 | + - **OpenID Connect scopes**: Select scopes your application needs (e.g., `openid`, `email`, `profile`) |
| 83 | + |
| 84 | + <Tip> |
| 85 | + For local development, you can use `http://localhost` URLs. For production, you must use HTTPS. |
| 86 | + </Tip> |
| 87 | +</Step> |
| 88 | + |
| 89 | +<Step title="Pick Up AWS Cognito Domain"> |
| 90 | + Navigate to **"Branding" → "Domain"** in the side navigation to find or configure Your AWS Cognito domain: |
| 91 | + |
| 92 | + **Option 1: Use Auto-Generated Domain** |
| 93 | + - If AWS has already created a domain automatically, note the **domain prefix** (the part before `.auth.region.amazoncognito.com`) |
| 94 | + - This prefix is what you'll use in your FastMCP configuration |
| 95 | + |
| 96 | + **Option 2: Create a Custom Domain Prefix** |
| 97 | + - If no domain exists or you want a better name, delete the existing domain and create a new one using the **"Actions"** menu |
| 98 | + - Under **"Domain"** → **"Cognito domain"** in the **"Create Cognito domain"** dialog, enter a meaningful prefix (e.g., `my-app`) that is available in the AWS region you are in |
| 99 | + - Just note the **domain prefix** you entered (e.g., `my-fastmcp-app`) - this is what you'll use in your FastMCP configuration |
| 100 | + |
| 101 | + <Info> |
| 102 | + The FastMCP AWS Cognito provider automatically constructs the full domain from your prefix and region, simplifying configuration. |
| 103 | + </Info> |
| 104 | +</Step> |
| 105 | + |
| 106 | +<Step title="Save Your Credentials"> |
| 107 | + After setup, you'll have: |
| 108 | + |
| 109 | + - **User Pool ID**: Format like `eu-central-1_XXXXXXXXX` |
| 110 | + - **Client ID**: Your application's client identifier |
| 111 | + - **Client Secret**: Generated client secret (keep secure) |
| 112 | + - **Domain Prefix**: The prefix of Your AWS Cognito domain |
| 113 | + - **AWS Region**: Where Your AWS Cognito user pool is located |
| 114 | + |
| 115 | + <Tip> |
| 116 | + Store these credentials securely. Never commit them to version control. Use environment variables or AWS Secrets Manager in production. |
| 117 | + </Tip> |
| 118 | +</Step> |
| 119 | +</Steps> |
| 120 | + |
| 121 | +### Step 2: FastMCP Configuration |
| 122 | + |
| 123 | +Create your FastMCP server using the `AWSCognitoProvider`, which handles AWS Cognito's JWT tokens and user claims automatically: |
| 124 | + |
| 125 | +```python server.py |
| 126 | +from fastmcp import FastMCP |
| 127 | +from fastmcp.server.auth.providers.aws import AWSCognitoProvider |
| 128 | +from fastmcp.server.dependencies import get_access_token |
| 129 | + |
| 130 | +# The AWSCognitoProvider handles JWT validation and user claims |
| 131 | +auth_provider = AWSCognitoProvider( |
| 132 | + user_pool_id="eu-central-1_XXXXXXXXX", # Your AWS Cognito user pool ID |
| 133 | + aws_region="eu-central-1", # AWS region (defaults to eu-central-1) |
| 134 | + client_id="your-app-client-id", # Your app client ID |
| 135 | + client_secret="your-app-client-secret", # Your app client Secret |
| 136 | + base_url="http://localhost:8000", # Must match your callback URL |
| 137 | + # redirect_path="/auth/callback" # Default value, customize if needed |
| 138 | +) |
| 139 | + |
| 140 | +mcp = FastMCP(name="AWS Cognito Secured App", auth=auth_provider) |
| 141 | + |
| 142 | +# Add a protected tool to test authentication |
| 143 | +@mcp.tool |
| 144 | +async def get_access_token_claims() -> dict: |
| 145 | + """Get the authenticated user's access token claims.""" |
| 146 | + token = get_access_token() |
| 147 | + return { |
| 148 | + "sub": token.claims.get("sub"), |
| 149 | + "username": token.claims.get("username"), |
| 150 | + "cognito:groups": token.claims.get("cognito:groups", []), |
| 151 | + } |
| 152 | +``` |
| 153 | + |
| 154 | +## Testing |
| 155 | + |
| 156 | +### Running the Server |
| 157 | + |
| 158 | +Start your FastMCP server with HTTP transport to enable OAuth flows: |
| 159 | + |
| 160 | +```bash |
| 161 | +fastmcp run server.py --transport http --port 8000 |
| 162 | +``` |
| 163 | + |
| 164 | +Your server is now running and protected by AWS Cognito OAuth authentication. |
| 165 | + |
| 166 | +### Testing with a Client |
| 167 | + |
| 168 | +Create a test client that authenticates with Your AWS Cognito-protected server: |
| 169 | + |
| 170 | +```python test_client.py |
| 171 | +from fastmcp import Client |
| 172 | +import asyncio |
| 173 | + |
| 174 | +async def main(): |
| 175 | + # The client will automatically handle AWS Cognito OAuth |
| 176 | + async with Client("http://localhost:8000/mcp/", auth="oauth") as client: |
| 177 | + # First-time connection will open AWS Cognito login in your browser |
| 178 | + print("✓ Authenticated with AWS Cognito!") |
| 179 | + |
| 180 | + # Test the protected tool |
| 181 | + print("Calling protected tool: get_access_token_claims") |
| 182 | + result = await client.call_tool("get_access_token_claims") |
| 183 | + user_data = result.data |
| 184 | + print("Available access token claims:") |
| 185 | + print(f"- sub: {user_data.get('sub', 'N/A')}") |
| 186 | + print(f"- username: {user_data.get('username', 'N/A')}") |
| 187 | + print(f"- cognito:groups: {user_data.get('cognito:groups', [])}") |
| 188 | + |
| 189 | +if __name__ == "__main__": |
| 190 | + asyncio.run(main()) |
| 191 | +``` |
| 192 | + |
| 193 | +When you run the client for the first time: |
| 194 | +1. Your browser will open to AWS Cognito's hosted UI login page |
| 195 | +2. After you sign in (or sign up), you'll be redirected back to your MCP server |
| 196 | +3. The client receives the JWT token and can make authenticated requests |
| 197 | + |
| 198 | +<Info> |
| 199 | +The client caches tokens locally, so you won't need to re-authenticate for subsequent runs unless the token expires or you explicitly clear the cache. |
| 200 | +</Info> |
| 201 | + |
| 202 | +## Environment Variables |
| 203 | + |
| 204 | +For production deployments, use environment variables instead of hardcoding credentials. |
| 205 | + |
| 206 | +### Provider Selection |
| 207 | + |
| 208 | +Setting this environment variable allows the AWS Cognito provider to be used automatically without explicitly instantiating it in code. |
| 209 | + |
| 210 | +<Card> |
| 211 | +<ParamField path="FASTMCP_SERVER_AUTH" default="Not set"> |
| 212 | +Set to `fastmcp.server.auth.providers.aws.AWSCognitoProvider` to use AWS Cognito authentication. |
| 213 | +</ParamField> |
| 214 | +</Card> |
| 215 | + |
| 216 | +### AWS Cognito-Specific Configuration |
| 217 | + |
| 218 | +These environment variables provide default values for the AWS Cognito provider, whether it's instantiated manually or configured via `FASTMCP_SERVER_AUTH`. |
| 219 | + |
| 220 | +<Card> |
| 221 | +<ParamField path="FASTMCP_SERVER_AUTH_AWS_COGNITO_USER_POOL_ID" required> |
| 222 | +Your AWS Cognito user pool ID (e.g., `eu-central-1_XXXXXXXXX`) |
| 223 | +</ParamField> |
| 224 | + |
| 225 | +<ParamField path="FASTMCP_SERVER_AUTH_AWS_COGNITO_AWS_REGION" default="eu-central-1"> |
| 226 | +AWS region where your AWS Cognito user pool is located |
| 227 | +</ParamField> |
| 228 | + |
| 229 | +<ParamField path="FASTMCP_SERVER_AUTH_AWS_COGNITO_CLIENT_ID" required> |
| 230 | +Your AWS Cognito app client ID |
| 231 | +</ParamField> |
| 232 | + |
| 233 | +<ParamField path="FASTMCP_SERVER_AUTH_AWS_COGNITO_CLIENT_SECRET" required> |
| 234 | +Your AWS Cognito app client secret |
| 235 | +</ParamField> |
| 236 | + |
| 237 | +<ParamField path="FASTMCP_SERVER_AUTH_AWS_COGNITO_BASE_URL" default="http://localhost:8000"> |
| 238 | +Public URL of your FastMCP server for OAuth callbacks |
| 239 | +</ParamField> |
| 240 | + |
| 241 | +<ParamField path="FASTMCP_SERVER_AUTH_AWS_COGNITO_REDIRECT_PATH" default="/auth/callback"> |
| 242 | +One of the redirect paths configured in your AWS Cognito app client |
| 243 | +</ParamField> |
| 244 | + |
| 245 | +<ParamField path="FASTMCP_SERVER_AUTH_AWS_COGNITO_REQUIRED_SCOPES" default='["openid"]'> |
| 246 | +Comma-, space-, or JSON-separated list of required OAuth scopes (e.g., `openid email` or `["openid","email","profile"]`) |
| 247 | +</ParamField> |
| 248 | +</Card> |
| 249 | + |
| 250 | +Example `.env` file: |
| 251 | +```bash |
| 252 | +# Use the AWS Cognito provider |
| 253 | +FASTMCP_SERVER_AUTH=fastmcp.server.auth.providers.aws.AWSCognitoProvider |
| 254 | + |
| 255 | +# AWS Cognito credentials |
| 256 | +FASTMCP_SERVER_AUTH_AWS_COGNITO_USER_POOL_ID=eu-central-1_XXXXXXXXX |
| 257 | +FASTMCP_SERVER_AUTH_AWS_COGNITO_AWS_REGION=eu-central-1 |
| 258 | +FASTMCP_SERVER_AUTH_AWS_COGNITO_CLIENT_ID=your-app-client-id |
| 259 | +FASTMCP_SERVER_AUTH_AWS_COGNITO_CLIENT_SECRET=your-app-client-secret |
| 260 | +FASTMCP_SERVER_AUTH_AWS_COGNITO_BASE_URL=https://your-server.com |
| 261 | +FASTMCP_SERVER_AUTH_AWS_COGNITO_REQUIRED_SCOPES=openid,email,profile |
| 262 | +``` |
| 263 | + |
| 264 | +With environment variables set, your server code simplifies to: |
| 265 | + |
| 266 | +```python server.py |
| 267 | +from fastmcp import FastMCP |
| 268 | +from fastmcp.server.dependencies import get_access_token |
| 269 | + |
| 270 | +# Authentication is automatically configured from environment |
| 271 | +mcp = FastMCP(name="AWS Cognito Secured App") |
| 272 | + |
| 273 | +@mcp.tool |
| 274 | +async def get_access_token_claims() -> dict: |
| 275 | + """Get the authenticated user's access token claims.""" |
| 276 | + token = get_access_token() |
| 277 | + return { |
| 278 | + "sub": token.claims.get("sub"), |
| 279 | + "username": token.claims.get("username"), |
| 280 | + "cognito:groups": token.claims.get("cognito:groups", []), |
| 281 | + } |
| 282 | +``` |
| 283 | + |
| 284 | +## Features |
| 285 | + |
| 286 | +### JWT Token Validation |
| 287 | + |
| 288 | +The AWS Cognito provider includes robust JWT token validation: |
| 289 | + |
| 290 | +- **Signature Verification**: Validates tokens against AWS Cognito's public keys (JWKS) |
| 291 | +- **Expiration Checking**: Automatically rejects expired tokens |
| 292 | +- **Issuer Validation**: Ensures tokens come from your specific AWS Cognito user pool |
| 293 | +- **Scope Enforcement**: Verifies required OAuth scopes are present |
| 294 | + |
| 295 | +### User Claims and Groups |
| 296 | + |
| 297 | +Access rich user information from AWS Cognito JWT tokens: |
| 298 | + |
| 299 | +```python |
| 300 | +from fastmcp.server.dependencies import get_access_token |
| 301 | + |
| 302 | +@mcp.tool |
| 303 | +async def admin_only_tool() -> str: |
| 304 | + """A tool only available to admin users.""" |
| 305 | + token = get_access_token() |
| 306 | + user_groups = token.claims.get("cognito:groups", []) |
| 307 | + |
| 308 | + if "admin" not in user_groups: |
| 309 | + raise ValueError("This tool requires admin access") |
| 310 | + |
| 311 | + return "Admin access granted!" |
| 312 | +``` |
| 313 | + |
| 314 | +### Enterprise Integration |
| 315 | + |
| 316 | +Perfect for enterprise environments with: |
| 317 | + |
| 318 | +- **Single Sign-On (SSO)**: Integrate with corporate identity providers |
| 319 | +- **Multi-Factor Authentication (MFA)**: Leverage AWS Cognito's built-in MFA |
| 320 | +- **User Groups**: Role-based access control through AWS Cognito groups |
| 321 | +- **Custom Attributes**: Access custom user attributes defined in your AWS Cognito user pool |
| 322 | +- **Compliance**: Meet enterprise security and compliance requirements |
0 commit comments