I need to upload one file in Android to an s3 bucket. We want to authenticate the upload with Cognito User pools.
The standard way to do this would be to use the Storage API from the Amazon Amplify SDK.
Problem is that I need to report upload progress for the upload, and Amplify Storage does not allow you to set a listener to observe Progress in Android.
That takes me to the need of using TransferUtility
.
How I am supposed to authenticate the upload operation using Cognito with TransferUtility?
At the moment I'm doing:
val credentials = CognitoCachingCredentialsProvider(
context,
"eu-west-1:XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
Regions.US_WEST_1)
val s3Client = AmazonS3Client(credentials, Region.getRegion(Regions.US_WEST_1))
val transferUtility = TransferUtility.builder()
.context(context)
.s3Client(s3Client)
.build()
But I'm getting a 403:
com.amazonaws.services.s3.model.AmazonS3Exception: Access Denied (Service: Amazon S3; Status Code: 403; Error Code: AccessDenied; Request ID: XXXXXXXXXXX), S3 Extended Request ID: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXx=
I'm really struggling to get any documentation for this, as it seems the Storage
API is now preferred over TransferUtility
, and everything to do with Cognito user pools or user identities is done with Amplitude Storage
I've finally found some documentation do to this.
Basically, you use AWSMobileClient
as the implementation for the AWSConfiguration
with building the TransferUtility
TransferUtility transferUtility =
TransferUtility.builder()
.context(getApplicationContext())
.awsConfiguration(AWSMobileClient.getInstance().getConfiguration())
.s3Client(new AmazonS3Client(AWSMobileClient.getInstance().getCredentialsProvider()))
.build();
TransferObserver uploadObserver =
transferUtility.upload(
"s3Folder/s3Key.txt",
new File("/path/to/file/localFile.txt"));
Also, there are two other caveats I had to figure out to make this work without receiving HTTP 403:
awsconfiguration.json
{
"IdentityManager": {
"Default": {}
},
"CognitoUserPool": {
"Default": {
"PoolId": "region_XXXXXXX",
"AppClientId": "XXXXXXXXXXXXXXX",
"Region": "XXXXX"
}
},
"CredentialsProvider": {
"CognitoIdentity": {
"Default": {
"PoolId": "XXXXX:XXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
"Region": "XXXXXX"
}
}
},
"S3TransferUtility": {
"Default": {
"Bucket": "XXXXXXXXXXXXXXXXXXX-data-bucket",
"Region": "XXXXXX"
}
}
}
Note that CredentialsProvider.CognitoIdentity.Default.PoolId
is not the same as
CognitoUserPool.Default.PoolId
!
key
when performing the upload if required, depending on the server-side configuration.