You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于AWS Cognito、API Gateway与Serverless的角色权限配置咨询

Hey there, let’s tackle your AWS permissions head-on. You’ve got three solid ideas, but the best approach is combining Cognito User Groups + IAM Roles (your first option) with a Pre-Token Generator Trigger (your third option). This leverages AWS’s native security tools, keeps maintenance low, and gives you both API-level and function-level control—perfect for your admin/regular user split.

Why This Combo Is Your Best Bet

  • IAM Authorization is AWS’s battle-tested, native way to lock down API access. No custom token validation code means fewer security gaps and less maintenance overhead.
  • Cognito User Groups simplify permission management: just add users to AdminGroup or RegularUserGroup instead of manually assigning roles to individual users.
  • Pre-Token Trigger injects user group info into your access/ID tokens, letting you add extra fine-grained checks in Lambda if needed (like restricting specific admin actions within an allowed API).

Comparing this to your other options:

  • Custom authorizers work, but require writing and maintaining your own token validation logic—unnecessary when AWS’s native tools do this better.
  • Using only a Pre-Token Trigger means you’d have to add permission checks to every Lambda function, which is error-prone and less efficient than blocking requests at the API Gateway level.

Full Implementation with Serverless Framework

Let’s build out the entire setup step by step.

Step 1: Serverless.yml Configuration

This defines all your AWS resources (Cognito, IAM roles, Lambdas, API Gateway) in one place.

service: aws-api-permission-control

provider:
  name: aws
  runtime: nodejs18.x
  stage: dev
  region: us-east-1
  iam:
    role:
      statements:
        # Allow Lambdas to access Cognito group data
        - Effect: Allow
          Action: cognito-idp:AdminListGroupsForUser
          Resource: !GetAtt UserPool.Arn

functions:
  # API Lambda Functions
  getUser:
    handler: handlers/getUser.handler
    events:
      - http:
          path: user
          method: get
          authorizer: aws_iam # Enforce IAM authorization

  getVehicle:
    handler: handlers/getVehicle.handler
    events:
      - http:
          path: vehicle
          method: get
          authorizer: aws_iam

  postVehicle:
    handler: handlers/postVehicle.handler
    events:
      - http:
          path: vehicle
          method: post
          authorizer: aws_iam

resources:
  Resources:
    # Cognito User Pool
    UserPool:
      Type: AWS::Cognito::UserPool
      Properties:
        UserPoolName: ${self:service}-user-pool-${self:provider.stage}
        UsernameAttributes: [email]
        AutoVerifiedAttributes: [email]
        Schema:
          - Name: email
            AttributeDataType: String
            Mutable: false
            Required: true

    # User Pool Client (for app authentication)
    UserPoolClient:
      Type: AWS::Cognito::UserPoolClient
      Properties:
        UserPoolId: !Ref UserPool
        ClientName: ${self:service}-client-${self:provider.stage}
        GenerateSecret: false
        ExplicitAuthFlows:
          - ALLOW_USER_PASSWORD_AUTH
          - ALLOW_REFRESH_TOKEN_AUTH

    # IAM Role for Admin Users (full API access)
    AdminIAMRole:
      Type: AWS::IAM::Role
      Properties:
        RoleName: ${self:service}-admin-role-${self:provider.stage}
        AssumeRolePolicyDocument:
          Version: '2012-10-17'
          Statement:
            - Effect: Allow
              Principal: { Federated: cognito-identity.amazonaws.com }
              Action: sts:AssumeRoleWithWebIdentity
              Condition:
                StringEquals:
                  cognito-identity.amazonaws.com:aud: !Ref CognitoIdentityPool
                ForAnyValue:StringLike:
                  cognito-identity.amazonaws.com:amr: authenticated
        Policies:
          - PolicyName: AdminAPIAccess
            PolicyDocument:
              Version: '2012-10-17'
              Statement:
                - Effect: Allow
                  Action: execute-api:Invoke
                  Resource:
                    - !Sub "arn:aws:execute-api:${self:provider.region}:${AWS::AccountId}:${ApiGatewayRestApi}/*/GET/user"
                    - !Sub "arn:aws:execute-api:${self:provider.region}:${AWS::AccountId}:${ApiGatewayRestApi}/*/GET/vehicle"
                    - !Sub "arn:aws:execute-api:${self:provider.region}:${AWS::AccountId}:${ApiGatewayRestApi}/*/POST/vehicle"

    # IAM Role for Regular Users (only GET /vehicle access)
    RegularUserIAMRole:
      Type: AWS::IAM::Role
      Properties:
        RoleName: ${self:service}-regular-role-${self:provider.stage}
        AssumeRolePolicyDocument:
          Version: '2012-10-17'
          Statement:
            - Effect: Allow
              Principal: { Federated: cognito-identity.amazonaws.com }
              Action: sts:AssumeRoleWithWebIdentity
              Condition:
                StringEquals:
                  cognito-identity.amazonaws.com:aud: !Ref CognitoIdentityPool
                ForAnyValue:StringLike:
                  cognito-identity.amazonaws.com:amr: authenticated
        Policies:
          - PolicyName: RegularUserAPIAccess
            PolicyDocument:
              Version: '2012-10-17'
              Statement:
                - Effect: Allow
                  Action: execute-api:Invoke
                  Resource:
                    - !Sub "arn:aws:execute-api:${self:provider.region}:${AWS::AccountId}:${ApiGatewayRestApi}/*/GET/vehicle"

    # Cognito Identity Pool (maps user groups to IAM roles)
    CognitoIdentityPool:
      Type: AWS::Cognito::IdentityPool
      Properties:
        IdentityPoolName: ${self:service}-identity-pool-${self:provider.stage}
        AllowUnauthenticatedIdentities: false
        CognitoIdentityProviders:
          - ClientId: !Ref UserPoolClient
            ProviderName: !GetAtt UserPool.ProviderName

    # Map User Groups to IAM Roles
    IdentityPoolRoleAttachment:
      Type: AWS::Cognito::IdentityPoolRoleAttachment
      Properties:
        IdentityPoolId: !Ref CognitoIdentityPool
        Roles:
          authenticated: !GetAtt RegularUserIAMRole.Arn # Default for authenticated users
        RoleMappings:
          AdminGroupMapping:
            Type: Token
            AmbiguousRoleResolution: AuthenticatedRole
            IdentityProvider: !Sub "cognito-idp.${self:provider.region}.amazonaws.com/${!Ref UserPool}"
            RulesConfiguration:
              Rules:
                - Claim: cognito:groups
                  MatchType: Contains
                  Value: AdminGroup
                  RoleARN: !GetAtt AdminIAMRole.Arn

    # Cognito User Groups
    AdminGroup:
      Type: AWS::Cognito::UserPoolGroup
      Properties:
        GroupName: AdminGroup
        UserPoolId: !Ref UserPool
        Description: Full API access for admins

    RegularUserGroup:
      Type: AWS::Cognito::UserPoolGroup
      Properties:
        GroupName: RegularUserGroup
        UserPoolId: !Ref UserPool
        Description: Limited access for regular users

    # Pre-Token Generator Lambda (adds group info to tokens)
    PreTokenGeneratorLambda:
      Type: AWS::Lambda::Function
      Properties:
        FunctionName: ${self:service}-pre-token-${self:provider.stage}
        Runtime: nodejs18.x
        Handler: pre-token-generator.handler
        Role: !GetAtt LambdaExecutionRole.Arn
        Code:
          ZipFile: |
            exports.handler = async (event) => {
              const { username, userPoolId } = event.request.userAttributes;
              const AWS = require('aws-sdk');
              const cognito = new AWS.CognitoIdentityServiceProvider();

              try {
                const groups = await cognito.adminListGroupsForUser({
                  Username: username,
                  UserPoolId: userPoolId
                }).promise();

                // Inject group info into token claims
                event.response = {
                  claimsOverrideDetails: {
                    claimsToAddOrOverride: {
                      'cognito:groups': groups.Groups.map(g => g.GroupName),
                      'custom:user_role': groups.Groups[0]?.GroupName || 'RegularUserGroup'
                    }
                  }
                };
              } catch (err) {
                console.error('Failed to fetch user groups:', err);
              }

              return event;
            };

    # Lambda Execution Role for Pre-Token Trigger
    LambdaExecutionRole:
      Type: AWS::IAM::Role
      Properties:
        RoleName: ${self:service}-lambda-exec-role-${self:provider.stage}
        AssumeRolePolicyDocument:
          Version: '2012-10-17'
          Statement:
            - Effect: Allow
              Principal: { Service: lambda.amazonaws.com }
              Action: sts:AssumeRole
        Policies:
          - PolicyName: CognitoAccess
            PolicyDocument:
              Version: '2012-10-17'
              Statement:
                - Effect: Allow
                  Action: cognito-idp:AdminListGroupsForUser
                  Resource: !GetAtt UserPool.Arn
          - PolicyName: LambdaLogging
            PolicyDocument:
              Version: '2012-10-17'
              Statement:
                - Effect: Allow
                  Action:
                    - logs:CreateLogGroup
                    - logs:CreateLogStream
                    - logs:PutLogEvents
                  Resource: arn:aws:logs:*:*:*

    # Attach Pre-Token Trigger to User Pool
    UserPoolPreTokenTrigger:
      Type: AWS::Cognito::UserPoolTrigger
      Properties:
        UserPoolId: !Ref UserPool
        TriggerType: PreTokenGeneration
        LambdaArn: !GetAtt PreTokenGeneratorLambda.Arn

Step 2: Lambda Handler Examples

Add these files in a handlers/ directory to implement your business logic, with optional extra permission checks.

handlers/getUser.js (Admin-only)

exports.handler = async (event) => {
  // Optional: Double-check user is in AdminGroup (extra security layer)
  const userGroups = event.requestContext.authorizer.claims['cognito:groups'];
  if (!userGroups.includes('AdminGroup')) {
    return {
      statusCode: 403,
      body: JSON.stringify({ message: 'Forbidden: Admin access required' })
    };
  }

  // Your admin-only logic here
  return {
    statusCode: 200,
    body: JSON.stringify({ user: 'Admin-specific user data' })
  };
};

handlers/getVehicle.js (All users)

exports.handler = async (event) => {
  // Optional: Verify user is in an allowed group
  const userGroups = event.requestContext.authorizer.claims['cognito:groups'];
  if (!userGroups.includes('AdminGroup') && !userGroups.includes('RegularUserGroup')) {
    return { statusCode: 403, body: JSON.stringify({ message: 'Forbidden' }) };
  }

  // Your vehicle fetch logic here
  return {
    statusCode: 200,
    body: JSON.stringify({ vehicles: ['Sedan', 'Truck'] })
  };
};

handlers/postVehicle.js (Admin-only)

exports.handler = async (event) => {
  const userGroups = event.requestContext.authorizer.claims['cognito:groups'];
  if (!userGroups.includes('AdminGroup')) {
    return { statusCode: 403, body: JSON.stringify({ message: 'Forbidden: Admin access required' }) };
  }

  // Your vehicle creation logic here
  return {
    statusCode: 201,
    body: JSON.stringify({ message: 'Vehicle created successfully' })
  };
};

Step 3: Test the Setup

  1. Deploy the stack: Run serverless deploy in your project directory.
  2. Create users: Use the AWS Console or CLI to create two Cognito users, then add one to AdminGroup and the other to RegularUserGroup.
  3. Authenticate to get a token:
    aws cognito-idp initiate-auth --client-id <YOUR_USER_POOL_CLIENT_ID> --auth-flow USER_PASSWORD_AUTH --auth-parameters USERNAME=<USER_EMAIL>,PASSWORD=<USER_PASSWORD>
    
  4. Call the APIs: Use tools like Postman or curl to send requests with the Authorization: Bearer <ACCESS_TOKEN> header:
    • Admin users can access all three APIs.
    • Regular users will get a 403 error for GET /user and POST /vehicle, but can access GET /vehicle.

内容的提问来源于stack exchange,提问作者Philipp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:37:54