aws-amplify / amplify-js

A declarative JavaScript library for application development using cloud services.
https://docs.amplify.aws/lib/q/platform/js
Apache License 2.0
9.4k stars 2.11k forks source link

Can't download or view uploaded files in S3 #13564

Open juri-diener opened 5 days ago

juri-diener commented 5 days ago

Before opening, please confirm:

JavaScript Framework

React Native

Amplify APIs

GraphQL API, Storage

Amplify Version

v6

Amplify Categories

auth, storage, function, api

Backend

Amplify CLI

Environment information

``` # Put output below this line System: OS: macOS 14.3.1 CPU: (8) arm64 Apple M1 Memory: 296.64 MB / 16.00 GB Shell: 5.9 - /bin/zsh Binaries: Node: 21.7.3 - /opt/homebrew/bin/node npm: 10.5.0 - /opt/homebrew/bin/npm Watchman: 2024.05.06.00 - /opt/homebrew/bin/watchman Browsers: Chrome: 126.0.6478.127 Safari: 17.3.1 npmPackages: @aws-amplify/cli: ^11.0.5 => 11.0.5 @aws-amplify/react-native: ^1.0.28 => 1.0.28 @aws-amplify/ui-react-native: ^2.1.5 => 2.1.5 @babel/core: ^7.20.0 => 7.24.4 @babel/plugin-proposal-export-namespace-from: ^7.18.9 => 7.18.9 @expo/metro-runtime: ~3.1.3 => 3.1.3 @react-native-async-storage/async-storage: ^1.23.1 => 1.23.1 @react-native-community/netinfo: ^11.3.1 => 11.3.1 @types/react: ~18.2.45 => 18.2.79 HelloWorld: 0.0.1 aws-amplify: ^6.0.28 => 6.0.28 aws-amplify/adapter-core: undefined () aws-amplify/analytics: undefined () aws-amplify/analytics/kinesis: undefined () aws-amplify/analytics/kinesis-firehose: undefined () aws-amplify/analytics/personalize: undefined () aws-amplify/analytics/pinpoint: undefined () aws-amplify/api: undefined () aws-amplify/api/server: undefined () aws-amplify/auth: undefined () aws-amplify/auth/cognito: undefined () aws-amplify/auth/cognito/server: undefined () aws-amplify/auth/enable-oauth-listener: undefined () aws-amplify/auth/server: undefined () aws-amplify/data: undefined () aws-amplify/data/server: undefined () aws-amplify/datastore: undefined () aws-amplify/in-app-messaging: undefined () aws-amplify/in-app-messaging/pinpoint: undefined () aws-amplify/push-notifications: undefined () aws-amplify/push-notifications/pinpoint: undefined () aws-amplify/storage: undefined () aws-amplify/storage/s3: undefined () aws-amplify/storage/s3/server: undefined () aws-amplify/storage/server: undefined () aws-amplify/utils: undefined () date-fns: ^3.6.0 => 3.6.0 expo: ~50.0.14 => 50.0.17 expo-av: ~13.10.6 => 13.10.6 expo-constants: ~15.4.6 => 15.4.6 expo-dev-client: ~3.3.12 => 3.3.12 expo-device: ~5.9.4 => 5.9.4 expo-image-manipulator: ~11.8.0 => 11.8.0 expo-image-picker: ~14.7.1 => 14.7.1 expo-linking: ~6.2.2 => 6.2.2 expo-notifications: ~0.27.7 => 0.27.7 expo-router: ~3.4.8 => 3.4.8 expo-status-bar: ~1.11.1 => 1.11.1 react: 18.2.0 => 18.2.0 react-dom: 18.2.0 => 18.2.0 react-native: 0.73.6 => 0.73.6 react-native-gesture-handler: ~2.14.0 => 2.14.1 react-native-get-random-values: ^1.11.0 => 1.11.0 react-native-keyboard-aware-scroll-view: ^0.9.5 => 0.9.5 react-native-reanimated: ~3.6.2 => 3.6.3 react-native-safe-area-context: 4.8.2 => 4.8.2 react-native-screens: ~3.29.0 => 3.29.0 react-native-web: ~0.19.6 => 0.19.10 typescript: ^5.1.3 => 5.4.5 zustand: ^4.5.2 => 4.5.2 npmGlobalPackages: @aws-amplify/cli: 12.11.1 eas-cli: 9.0.6 n: 9.1.0 npm: 10.5.0 ```

Describe the bug

Hello I can't get the files I uploaded to S3 because of a wrong identity id in my bucket.

User with the Id: 70fc.......a6fb uploads the file in S3 the file now ends up under: bucketname/protected/eu-north-1:be14......36aaa70/audio/filename

Where does this id come from? eu-north-1:be14......36aaa70

I thought the sub is used from cognito to identify the user. Because in the docs of the getURL function there is this field: targetIdentityId?: 'XXXXXXX', // id of another user, if accessLevel is protected And if I understand it right it should be the sub of the cognito user.

Because how would User B access User A uploaded files for example an profile image.

Please help me I don't know where to search for this issue, and I can't do anything further if this is not working.

Expected behavior

Should create under the bucket name/protected a folder with the user sub id. --> bucketname/protected/70fc.../audio/filename

Reproduction steps

  1. Create a bucket
  2. upload a image with the uploadData function
  3. S3 created under the bucketname/protected/use_sub_id/

Code Snippet

// Put your code below this line.
export const getFileUrl = async (
  filename: string,
  anotherUserId: string | undefined = undefined,
) => {
  let result;
  const userId = anotherUserId ? anotherUserId : userStrore.getState().id;
  try {
    const getUrlResult = await getUrl({
      key: filename,
      options: {
        accessLevel: "protected",
        targetIdentityId: userId,
      },
    });
    result = getUrlResult;
  } catch (e) {
    console.log("error on downloading image from the cloud");
  }
  return result;
};

export const uploadFile = async (
  fileUri: string,
  filename: string = "",
  setProgress: React.Dispatch<React.SetStateAction<number>>,
) => {
  const file = await getBlob(fileUri);
  const fileNameKey = filename ? filename : uuid();
  let result;

  const fileExt = fileUri.split(".").pop();
  const userId = userStrore.getState().id;

  let folder = "images";
  if (fileExt === "m4a") {
    folder = "audio";
  }

  try {
    result = await uploadData({
      key: `${folder}/${fileNameKey}.${fileExt}`,
      data: file,
      options: {
        accessLevel: "protected",
        onProgress: ({ transferredBytes, totalBytes }) => {
          if (totalBytes) {
            const total = Math.round((transferredBytes / totalBytes) * 100);
            setProgress(Number(total));
          }
        },
      },
    }).result;
  } catch (error) {
    console.warn("Error : ", error);
  }
  return result?.key;
};

Log output

``` // Put your logs below this line ```

aws-exports.js

No response

Manual configuration

No response

Additional configuration

No response

Mobile Device

No response

Mobile Operating System

No response

Mobile Browser

No response

Mobile Browser Version

No response

Additional information and screenshots

No response

HuiSF commented 4 days ago

Hi @juri-diener The ID string you were asking about is not a user sub, but a user identity ID. For details about the storage access level and prefix construction, see this documentation: https://docs.amplify.aws/gen1/react/build-a-backend/storage/configure-access/.

If you plan to access a file uploaded with a protected access level by a different user, you would need to record the identity ID of that user. You can get the user identity ID by calling fetchAuthSession()

In the meantime, if you are building something new, the above linked documentation also recommends starting with the Amplify Gen2 experience, which gives you much more freedom in file permission management. 

juri-diener commented 3 days ago

Hi @juri-diener The ID string you were asking about is not a user sub, but a user identity ID. For details about the storage access level and prefix construction, see this documentation: https://docs.amplify.aws/gen1/react/build-a-backend/storage/configure-access/.

If you plan to access a file uploaded with a protected access level by a different user, you would need to record the identity ID of that user. You can get the user identity ID by calling fetchAuthSession()

In the meantime, if you are building something new, the above linked documentation also recommends starting with the Amplify Gen2 experience, which gives you much more freedom in file permission management.

Hello, thank you for your answer. Why don't I see this ID anywhere? Even when I edit the cognito user in the backend, I don't see this ID with eu-north-1 anywhere.

To clarify, is the ID with eu-north-1 the correct user_identity-id?

And if so, do I have access in the Lambda function? Because after every signup, a Lambda function is executed and the cognito user is saved in my dynamodb table. And for that I need this ID so that I can access the S3 storage.

I started the project months ago. So I can't switch to gen2 for now. And this problem has been holding me back for a week now :( I would be really grateful if you could help me solve this.

cwomack commented 4 hours ago

@juri-diener, I think we're getting a better understanding of what you're looking to do now. Thank you for the additional context.

While you've already started building your app, we'd recommend both upgrading to the latest version of v6 (currently v6.4.0 and I think you're on v6.0.28) as well as make the transition to using Gen 2 based on what you're looking to accomplish. This will make it easier for you to use the custom authorization rules as well as define the path for the S3 bucket that you'd prefer (see this Gen 1 doc for more info).

Let us know if you're able to make this update, as it will give you more extensibility and customization long term.

juri-diener commented 3 hours ago

@juri-diener, I think we're getting a better understanding of what you're looking to do now. Thank you for the additional context.

While you've already started building your app, we'd recommend both upgrading to the latest version of v6 (currently v6.4.0 and I think you're on v6.0.28) as well as make the transition to using Gen 2 based on what you're looking to accomplish. This will make it easier for you to use the custom authorization rules as well as define the path for the S3 bucket that you'd prefer (see this Gen 1 doc for more info).

Let us know if you're able to make this update, as it will give you more extensibility and customization long term.

Ok thank you for your response. So just to clarify. The identity id with eu-north-1 at the beginning. Ist the correct id in S3 ? Or is something messed up on my configuration ? Because it seems to me still, that the id with the region is wrong. But if that's how it should be, then everything is fine, I need then just to know how I can access this ID on signup in a lambda function.

Is there a way how to update the version safely? Because I did an update of amplify CLI but then something else didn't worked as it should so I had to need to downgrade again. That's why I would prefer for now to stay on the version I have now. And only upgrade if my project is done. This means this problem with S3 I need to solve...