skip to Main Content

I am trying to create a desktop application, which sends user files to Amazon S3, where the users can then sign in to a website to view/download their files. I have the desktop application working, it has the user sign in and upload the files to their own bucket. I also have a webpage where the user can sign in to a Cognito user that has permissions to download files from that bucket. I can’t seem to link the Cognito user to their S3 permissions. All of the examples I have found involve linking the website to one bucket, and in this case, that bucket depends on the user they’re signed in to. This attempt to list buckets returns "Error: Credential is missing"

AWS amplify authentication (this successfully returns the user when credentials are entered):

export class CognitoService {

  private authenticationSubject: BehaviorSubject<any>;

  constructor() {
    Amplify.configure({
    Auth: environment.cognito,
  });

    this.authenticationSubject = new BehaviorSubject<boolean>(false);
  }


  public signIn(user: IUser): Promise<any> {
    return Auth.signIn(user.username, user.password)
      .then(returnedUser => {
        if (returnedUser.challengeName === 'NEW_PASSWORD_REQUIRED') {
          Auth.completeNewPassword(returnedUser, user.password)
            .then(user => {
              return user
            });
        }
      })
  }
  public getUser(): Promise<any> {
    return Auth.currentUserInfo();
  }
}

Get data (This request is unsuccessful at returning the S3 buckets)

export class DataComponent implements OnInit{
  user: IUser;

 constructor(private cognitoService: CognitoService, private s3Service: S3Service) {
    this.user = {} as IUser;
  }
  public ngOnInit(): void {
    this.cognitoService.getUser()
    .then((user: any) => {
      this.user = user.attributes;
    });
  }
  public getBuckets(): void {
    this.s3Service.getBuckets()
    .then((response: any) => {
      console.log(response)
    })
  }
}

S3 service used to get buckets (I suspect this is where changes are needed):

export class S3Service {
    constructor() {
        Amplify.configure({
            Auth: environment.cognito,
        });
    }

    public async getBuckets() {
        const client = new S3Client({region: 'us-west-2'});
        const input = {};
        const command = new ListBucketsCommand(input);
        const response = await client.send(command);
    }
}

Environment:

export const environment = {
    cognito: {
        userPoolId: 'xxx',
        userPoolWebClientId: 'xxx',
    },
}

2

Answers


  1. Chosen as BEST ANSWER

    Unfortunately I was having some issues assigning permissions using the temporary credentials. What I ended up doing was this:

    1. Changed the desktop application to upload to a folder inside of a bucket. Their IAM role then had access only to that folder. See below for specifying a folder inside a bucket.
            {
                "Sid": "VisualEditor0",
                "Effect": "Allow",
                "Action": [
                    "s3:PutObject",
                    "s3:GetObject",
                    "s3:GetBucketTagging",
                    "s3:ListBucket",
                    "s3:DeleteObject",
                    "s3:GetBucketAcl"
                ],
                "Resource": [
                    "arn:aws:s3:::{bucket}/{folder}",
                    "arn:aws:s3:::{bucket}/{folder}/*"
                ]
            },
    
    1. The website then has that bucket hard coded in, if they try to download a file from a different folder, then it returns "access denied".

  2. You could use Cognito user’s role giving permission to access the S3 bucket.

    It is possible to assign a role to any/all authenticated user and then use that role’s permissions

    https://aws.amazon.com/blogs/developer/amazon-cognito-credentials-provider/

    Seeing you are using the Amplify lib, it should allow you to get the aws session (temporary) credentials

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search