简体   繁体   English

AWS API网关Cognito - 如何从反应应用程序中获取

[英]AWS API gateway Cognito - How to fetch from react app

I try to add Cognito auth to an react app which calls an API gateway, too. 我尝试将Cognito auth添加到一个调用API网关的反应应用程序中。 I made it to have auth in the react app with: 我让它在反应应用程序中使用auth:

export default withAuthenticator(App);

But now I in addition want to make the API gateway secure with the same login. 但是现在我还想用同样的登录来保证API网关的安全。

Currently I get this error: 目前我收到此错误:

Access to fetch at '.../' from origin ' http://localhost:3000 ' has been blocked by CORS policy: Request header field access-control-allow-origin is not allowed by Access-Control-Allow-Headers in preflight response. 从“ http:// localhost:3000 ”获取“... /”的访问权限已被CORS策略阻止:Access-Control-Allow-Headers中不允许使用请求头字段access-control-allow-origin飞行前响应。

Tested different things I found online, but actually I haven't found what exactly I need to send as Authorization (Is token.sessionToken the right thing?) nor what the header needs in addition. 测试了我在网上找到的不同的东西,但实际上我还没有找到我需要发送什么作为授权(令牌.sessionToken正确的东西?)以及标头需要的内容。 The API call looks like this currently. API调用目前看起来像这样。

callAPI = async (url) => {
    let token = await Amplify.Auth.currentCredentials();
    console.log(token.sessionToken)
    const apiurl = 'https...?url=' + url
    const response = await fetch(apiurl, {
      method: 'GET',
      mode: 'cors',
      headers: {
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, PATCH',
        'Access-Control-Allow-Headers': 'Origin, X-Requested-With, Content-Type, Accept, Authorization',
        Authorization: token.sessionToken
      },
    })
    const data = await response.json();

Serverless of the API gateway + corresponding lambda: 无服务器的API网关+对应的lambda:

resources: 
...
  Resources:
...
    CognitoUserPool:
      Type: AWS::Cognito::UserPool
      Properties:
        UserPoolName: ${self:service}_user_pool
        MfaConfiguration: OFF
        UsernameAttributes:
          - email
        Policies:
          PasswordPolicy:
            MinimumLength: 8
            RequireLowercase: False
            RequireNumbers: False
            RequireSymbols: False
            RequireUppercase: False

    CognitoUserPoolClient:
      Type: AWS::Cognito::UserPoolClient
      Properties:
        ClientName: ${self:service}_client
        UserPoolId:
          Ref: CognitoUserPool   

    ApiGatewayAuthorizer: 
      Type: AWS::ApiGateway::Authorizer
      Properties: 
        Name: CognitoUserPool
        Type: COGNITO_USER_POOLS
        IdentitySource: method.request.header.Authorization
        RestApiId: 
          Ref: ApiGatewayRestApi
        ProviderARNs: 
          - Fn::GetAtt:
              - CognitoUserPool
              - Arn

    CognitoIdentityPool:
      Type: AWS::Cognito::IdentityPool
      Properties:
        IdentityPoolName: ${self:service}_identity_pool
        AllowUnauthenticatedIdentities: false
        CognitoIdentityProviders:
          - ClientId:
              Ref: CognitoUserPoolClient
            ProviderName:
              Fn::GetAtt: [CognitoUserPool, ProviderName]

    CognitoIdentityPoolRoles:
      Type: AWS::Cognito::IdentityPoolRoleAttachment
      Properties:
        IdentityPoolId:
          Ref: CognitoIdentityPool
        Roles:
          authenticated:
            Fn::GetAtt: [CognitoAuthRole, Arn]
          unauthenticated:
            Fn::GetAtt: [CognitoUnauthRole, Arn]

    CognitoAuthRole:
      Type: AWS::IAM::Role
      Properties:
        RoleName: appAuthRole
        Path: /
        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: "CognitoAuthorizedPolicy"
            PolicyDocument:
              Version: "2012-10-17"
              Statement:
                - Effect: "Allow"
                  Action:
                    - "mobileanalytics:PutEvents"
                    - "cognito-sync:*"
                    - "cognito-identity:*"
                  Resource: "*"
                - Effect: "Allow"
                  Action:
                    - "execute-api:Invoke"
                  Resource: "*"
    CognitoUnauthRole:
      Type: AWS::IAM::Role
      Properties:
        RoleName: appUnauthRole
        Path: /
        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": unauthenticated
        Policies:
          - PolicyName: "CognitoUnauthorizedPolicy"
            PolicyDocument:
              Version: "2012-10-17"
              Statement:
                - Effect: "Allow"
                  Action:
                    - "mobileanalytics:PutEvents"
                    - "cognito-sync:*"
                    - "cognito-identity:*"
                  Resource: "*"

... ...

functions:
  ampstoryscreenshotsStep1:
    handler: src/index.ampstoryscreenshotsStep1
    events:
      - http:
          path: '{proxy+}'
          method: get
          cors: true
          integration: lambda
          authorizer: 
              type: COGNITO_USER_POOLS
              authorizerId: 
                Ref: ApiGatewayAuthorizer

Would also be interesting to learn how to test this with postman? 学习如何用邮递员测试这个也很有趣?

Ok after checking docs + some test this is my solution. 检查文档+一些测试后确定这是我的解决方案。 This creates cognito user pool, identity pool and the auth for the api gateway 这为api网关创建了cognito用户池,标识池和auth

Serverless: 无服务器:

resources: 

  Resources:

...

    CognitoUserPool:
      Type: AWS::Cognito::UserPool
      Properties:
        UserPoolName: ${self:service}_user_pool     
        MfaConfiguration: OFF
        Policies:
          PasswordPolicy:
            MinimumLength: 8
            RequireLowercase: False
            RequireNumbers: False
            RequireSymbols: False
            RequireUppercase: False
        AutoVerifiedAttributes:
          - email

    CognitoUserPoolClient:
      Type: AWS::Cognito::UserPoolClient
      Properties:
        ClientName: ${self:service}_client
        UserPoolId:
          Ref: CognitoUserPool   

    CognitoIdentityPool:
      Type: AWS::Cognito::IdentityPool
      Properties:
        IdentityPoolName: ${self:service}_identity_pool
        AllowUnauthenticatedIdentities: false
        CognitoIdentityProviders:
          - ClientId:
              Ref: CognitoUserPoolClient
            ProviderName:
              Fn::GetAtt: [CognitoUserPool, ProviderName]

    CognitoIdentityPoolRoles:
      Type: AWS::Cognito::IdentityPoolRoleAttachment
      Properties:
        IdentityPoolId:
          Ref: CognitoIdentityPool
        Roles:
          authenticated:
            Fn::GetAtt: [CognitoAuthRole, Arn]
          unauthenticated:
            Fn::GetAtt: [CognitoUnauthRole, Arn]

    CognitoAuthRole:
      Type: AWS::IAM::Role
      Properties:
        RoleName: appAuthRole
        Path: /
        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: "CognitoAuthorizedPolicy"
            PolicyDocument:
              Version: "2012-10-17"
              Statement:
                - Effect: "Allow"
                  Action:
                    - "mobileanalytics:PutEvents"
                    - "cognito-sync:*"
                    - "cognito-identity:*"
                  Resource: "*"
                - Effect: "Allow"
                  Action:
                    - "execute-api:Invoke"
                  Resource: "*"

    CognitoUnauthRole:
      Type: AWS::IAM::Role
      Properties:
        RoleName: appUnauthRole
        Path: /
        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": unauthenticated
        Policies:
          - PolicyName: "CognitoUnauthorizedPolicy"
            PolicyDocument:
              Version: "2012-10-17"
              Statement:
                - Effect: "Allow"
                  Action:
                    - "mobileanalytics:PutEvents"
                    - "cognito-sync:*"
                    - "cognito-identity:*"
                  Resource: "*"

    GatewayResponseDefault4XX:
      Type: 'AWS::ApiGateway::GatewayResponse'
      Properties:
        ResponseParameters:
          gatewayresponse.header.Access-Control-Allow-Origin: "'*'"
          gatewayresponse.header.Access-Control-Allow-Headers: "'*'"
          gatewayresponse.header.Access-Control-Allow-Methods: "'GET,PUT,OPTIONS'"
        ResponseType: DEFAULT_4XX
        RestApiId:
          Ref: 'ApiGatewayRestApi'

    GatewayResponseDefault5XX:
      Type: 'AWS::ApiGateway::GatewayResponse'
      Properties:
        ResponseParameters:
          gatewayresponse.header.Access-Control-Allow-Origin: "'*'"
          gatewayresponse.header.Access-Control-Allow-Headers: "'*'"
          gatewayresponse.header.Access-Control-Allow-Methods: "'GET,PUT,OPTIONS'"
        ResponseType: DEFAULT_5XX
        RestApiId:
          Ref: 'ApiGatewayRestApi'

    ApiGatewayAuthorizer:
      DependsOn:
        - ApiGatewayRestApi
      Type: AWS::ApiGateway::Authorizer
      Properties:
        Name: cognito-authorizer
        IdentitySource: method.request.header.Authorization
        RestApiId:
          Ref: ApiGatewayRestApi
        Type: COGNITO_USER_POOLS
        ProviderARNs:
          - Fn::GetAtt: [CognitoUserPool, Arn]

functions:
  ampstoryscreenshotsStep1:
    handler: src/index.ampstoryscreenshotsStep1
    events:
      - http:
          path: '{proxy+}'
          method: get
          cors: true
          authorizer: 
            type: COGNITO_USER_POOLS
            authorizerId: 
              Ref: ApiGatewayAuthorizer

The order here is important. 这里的顺序很重要。

I query like this: 我这样查询:

callAPI = async (url) => {
    const user = await Amplify.Auth.currentAuthenticatedUser();
    const token = user.signInUserSession.idToken.jwtToken;
    const apiurl = config.apiGateway.URL + '/takescreenshots/?url=' + url

    console.log(apiurl)

    const response = await fetch(apiurl, {
      method: 'GET',
      headers: {
        Authorization: token
      },
    })
    const data = await response.json();

which just works if your signed in. 只有你登录后才能正常工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM