如何使用Cognito实现API访问权限的精细化控制
Great question! Let's walk through exactly how to lock down access so your two Cognito user groups can't reach each other's services. Since API Gateway is only validating the ID Token right now, we need to add checks for user group membership and tie that to resource access. Here's a step-by-step solution tailored to your stack:
1. Leverage Cognito Group Information in Token Validation
When a user authenticates via Cognito, their ID Token includes a cognito:groups claim that lists all groups they belong to. We can use this to enforce permissions in two key places:
Option A: Use a Lambda Authorizer (Custom Authorizer) in API Gateway
This is the cleanest approach because it handles permission checks before the request reaches your Lambda function. Here's how to set it up:
- Create a Lambda function that receives the incoming API request, extracts and validates the ID Token, checks the user's groups, and returns an allow/deny policy for the requested resource.
- Configure API Gateway to use this authorizer for all your protected API methods. The authorizer will block unauthorized requests early in the pipeline.
Option B: Check Groups Inside Your Lambda Functions
If you prefer to handle checks at the function level (or have existing logic there), you can:
- Extract the ID Token from the request headers (or the API Gateway event object).
- Validate and decode the token to get the
cognito:groupsclaim. - Immediately return a
403 Forbiddenresponse if the user's group doesn't have permission to access that service.
2. Properly Bind IAM Roles to Cognito User Groups
You mentioned you already have two user groups with different IAM roles—make sure these roles have strict, scoped permissions:
- For GroupA's role: Grant access only to ServiceA's Lambda function and its corresponding DynamoDB tables (use specific ARNs instead of wildcards).
- For GroupB's role: Do the same for ServiceB's resources.
- Note: These roles control what the user can do after accessing the API, so combining them with group-based API access checks creates a layered security model.
3. Example Lambda Authorizer Code
Here's a Python example that implements group-based access control:
import jwt from jwt import PyJWKClient def lambda_handler(event, context): # Extract the ID Token from the Authorization header try: token = event['authorizationToken'].split(' ')[1] except (KeyError, IndexError): return generate_policy('unauthorized', 'Deny', event['methodArn']) # Fetch Cognito public keys to validate the token (cache this in production!) jwks_url = "https://cognito-idp.<your-region>.amazonaws.com/<your-user-pool-id>/.well-known/jwks.json" jwks_client = PyJWKClient(jwks_url) try: signing_key = jwks_client.get_signing_key_from_jwt(token).key # Decode and validate the token (check audience, issuer, expiration) payload = jwt.decode( token, signing_key, algorithms=["RS256"], audience="<your-app-client-id>", issuer=f"https://cognito-idp.<your-region>.amazonaws.com/<your-user-pool-id>" ) except jwt.InvalidTokenError: return generate_policy('unauthorized', 'Deny', event['methodArn']) # Get the user's groups from the token payload user_groups = payload.get('cognito:groups', []) # Extract the target service from the API resource ARN resource_path = event['methodArn'].split('/')[2] # Enforce group-service matching if resource_path == 'serviceA' and 'GroupA' in user_groups: return generate_policy(payload['sub'], 'Allow', event['methodArn']) elif resource_path == 'serviceB' and 'GroupB' in user_groups: return generate_policy(payload['sub'], 'Allow', event['methodArn']) else: # Deny access if the group doesn't match the service return generate_policy(payload['sub'], 'Deny', event['methodArn']) def generate_policy(principal_id, effect, resource): """Helper function to create the IAM policy response""" return { 'principalId': principal_id, 'policyDocument': { 'Version': '2012-10-17', 'Statement': [{ 'Action': 'execute-api:Invoke', 'Effect': effect, 'Resource': resource }] } }
4. Additional Security Hardening Tips
- Cache Authorizer Results: API Gateway lets you set a TTL for Lambda Authorizer responses to reduce redundant token validation calls and improve performance.
- Strict Token Validation: Never skip checks for token expiration, audience, or issuer—this prevents tampered or invalid tokens from being used.
- Layered Permissions: Combine API Gateway authorizer checks with IAM policies on Lambda and DynamoDB. Even if someone bypasses the API layer, the underlying resources will still be protected.
内容的提问来源于stack exchange,提问作者Himanshu

