简体   繁体   English

在 React 中使用 aws-amplify 将文件上传到具有联合身份的 S3 时出错

[英]Getting Error while uploading file to S3 with Federated Identity using aws-amplify in React

While the user with Facebook federated Identity trying to upload Image, I'm getting an error: AWSS3Provider - error uploading Error: "Request failed with status code 403" Status Code: 403 Forbidden当具有 Facebook 联合身份的用户尝试上传图像时,我收到一个错误:AWSS3Provider - 上传错误错误:“请求失败,状态代码为 403”状态代码:403 Forbidden

Noticed that URL in request, while user authenticated with Federated Identity (Facebook), looks:注意到请求中的 URL 在用户使用联合身份 (Facebook) 进行身份验证时看起来:
Request URL: https://my-gallery-api-dev-photorepos3bucket-XXXX.s3.us-east-2.amazonaws.com/private/undefined/1587639369473-image.jpg?x-id=PutObject请求 URL: https://my-gallery-api-dev-photorepos3bucket-XXXX.s3.us-east-2.amazonaws.com/private/undefined/1587639-369473-image.jpg?

The folder where the uploaded image will be placed is 'undefined' instead of being a valid user identity like for users authenticated with from AWS UserPool, see:将放置上传图像的文件夹是“未定义” ,而不是像通过 AWS UserPool 进行身份验证的用户那样的有效用户身份,请参阅:
Request URL: https://my-gallery-api-dev-photorepos3bucket-XXXX.s3.us-east-2.amazonaws.com/private/us-east-2%3Aa2991437-264a-4652-a239-XXXXXXXXXXXX/1587636945392-image.jpg?x-id=PutObject Request URL: https://my-gallery-api-dev-photorepos3bucket-XXXX.s3.us-east-2.amazonaws.com/private/us-east-2%3Aa2991437-264a-4652-a239-XXXXXXXXXXXX/1587636945392 -image.jpg?x-id=PutObject

For Authentication and upload I'am using React aws dependency "aws-amplify": "^3.0.8"对于身份验证和上传,我正在使用 React aws 依赖"aws-amplify": "^3.0.8"

Facebook Authentication (Facebook Button): Facebook 认证(Facebook 按钮):

async handleResponse(data) {
    console.log("FB Response data:", data);
    const { userID, accessToken: token, expiresIn } = data;
    const expires_at = expiresIn * 1000 + new Date().getTime();
    const user = { userID };

    this.setState({ isLoading: true });
    console.log("User:", user);
    try {
      const response = await Auth.federatedSignIn(
        "facebook",
        { token, expires_at },
        user
      );
      this.setState({ isLoading: false });
      console.log("federatedSignIn Response:", response);
      this.props.onLogin(response);
    } catch (e) {
      this.setState({ isLoading: false })
      console.log("federatedSignIn Exception:", e);
      alert(e.message);
      this.handleError(e);
    }
  }

Uploading:上传:

import { Storage } from "aws-amplify";

export async function s3Upload(file) {
  const filename = `${Date.now()}-${file.name}`;

  const stored = await Storage.vault.put(filename, file, {
    contentType: file.type
  });

  return stored.key;
}
     const attachment = this.file
        ? await s3Upload(this.file)
        : null;

I'm understand that rejection by S3 with 403, because of the IAM role, I have for authenticated users:我知道由于 IAM 角色,S3 以 403 拒绝了经过身份验证的用户:

  # IAM role used for authenticated users
  CognitoAuthRole:
    Type: AWS::IAM::Role
    Properties:
      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: '*'

              # Allow users to invoke our API
              - Effect: 'Allow'
                Action:
                  - 'execute-api:Invoke'
                Resource:
                  Fn::Join:
                    - ''
                    -
                      - 'arn:aws:execute-api:'
                      - Ref: AWS::Region
                      - ':'
                      - Ref: AWS::AccountId
                      - ':'
                      - Ref: ApiGatewayRestApi
                      - '/*'

              # Allow users to upload attachments to their
              # folder inside our S3 bucket
              - Effect: 'Allow'
                Action:
                  - 's3:*'
                Resource:
                  - Fn::Join:
                    - ''
                    -
                      - Fn::GetAtt: [PhotoRepoS3Bucket, Arn]
                      - '/private/**${cognito-identity.amazonaws.com:sub}/***'
                  - Fn::Join:
                    - ''
                    -
                      - Fn::GetAtt: [PhotoRepoS3Bucket, Arn]
                      - '/private/**${cognito-identity.amazonaws.com:sub}**'

It works fine for users registered in AWS User Pool (Email, Password), but for federated users, there is no record in AWS User Pool only in Federated Identities, so there will be no cognito-identity.amazonaws.com:sub found for those users and directory 'undefined' not falling in role allowance for user identified with Federated Identity.它适用于在 AWS 用户池(电子邮件、密码)中注册的用户,但对于联合身份的用户,AWS 用户池中仅在联合身份中没有记录,因此不会有cognito-identity.amazonaws.com:sub found for那些用户和目录“未定义”不属于使用联合身份标识的用户的角色允许范围。

Please advise:请指教:
1. Where/how to fix this 'undefined' in URL? 1. 在哪里/如何在 URL 中修复这个“未定义”
2. Also, I would like, probably, to replace thouse Id's in upload URL to genereted user Id's from user database I'm going to add in near future. 2. 另外,我可能希望将上传 URL 中的 thouse Id 替换为我将在不久的将来添加的用户数据库中生成的用户 Id。 How to fix IAM Role to use custom Id's?如何修复 IAM 角色以使用自定义 ID?

I stumbled with the same problem when doing Serverless Stack tutorial在做无服务器堆栈教程时,我偶然发现了同样的问题

This error arises when you do the Extra Credit > React > Facebook Login with Cognito using AWS Amplify , as you have notice uploading a file fails if you're authenticated with Facebook.当您执行 Extra Credit > React > Facebook Login with Cognito using AWS Amplify时会出现此错误,因为您注意到如果您通过 Facebook 进行身份验证,上传文件将失败。

The error comes up when sending a PUT to:将 PUT 发送到:
https://<bucket>.s3.amazonaws.com/private/<identity-id>/<file>
...the <identity-id> is undefined so the PUT fails. ... <identity-id>未定义,因此 PUT 失败。

You can track down the source of this undefinition if you log what you get when running the login commands.如果您记录运行登录命令时获得的内容,则可以追踪此未定义的来源。 For example, when you login using your email and password, if you do:例如,当您使用 email 和密码登录时,如果您这样做:

await Auth.signIn(fields.email, fields.password);
const currCreds = await Auth.currentCredentials();
console.log('currCreds', currCreds);

...you can see that identityId is set correctly. ...您可以看到identityId设置正确。

On the other hand when you login with Facebook through Auth.federatedSignIn if you log the response you don't get identityId .另一方面,当您通过Auth.federatedSignIn使用 Facebook 登录时,如果您记录响应,您不会得到identityId Note: In the case you've previously logged in using email and password, it will remain the same, so this misconfiguration will also make uploading fail.注意:如果您之前使用 email 和密码登录,它将保持不变,因此此错误配置也会导致上传失败。

The workaround I've used is adding a simple lambda which returns the identityId for the logged in user, so once the user logs in with facebook, we ask for it and we can send the PUT to the correct url using AWS.S3().putObject The workaround I've used is adding a simple lambda which returns the identityId for the logged in user, so once the user logs in with facebook, we ask for it and we can send the PUT to the correct url using AWS.S3().putObject

In the case you want to try this out, take into account that you should host your React app in https as Facebook doesn't allow http domains.如果您想尝试这个,请考虑到您应该在 https 中托管您的 React 应用程序,因为 Facebook 不允许 http 域。 You can set this adding HTTPS=true to your React.env file.你可以设置这个添加HTTPS=true到你的 React.env 文件。

You can check my repos as example:您可以查看我的回购作为示例:
API API
Frontend前端

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

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