'How to Amazon S3 pre-signed URL from android app without exposing Amazon Web Services credentials
In my android app, I used Amazon S3 pre-signed URLs to display images in the app using the below code
var preSignedUrl = ""
val s3Client: AmazonS3Client?
val credentials: BasicAWSCredentials?
credentials = BasicAWSCredentials(BuildConfig.AWS_ACCESS_KEY_ID, BuildConfig.AWS_SECRET_ACCESS_KEY)
s3Client = AmazonS3Client(credentials)
try {
val s3URI = AmazonS3URI(imgUrl)
// Set the pre signed URL to expire after one day.
val expiration = Date()
var expTimeMillis: Long = Instant.now().toEpochMilli()
expTimeMillis += (1000 * 60 * 60 * 24 * 7).toLong()
expiration.time = expTimeMillis
val generateSignedUrlRequest = GeneratePresignedUrlRequest(s3URI.bucket, s3URI.key)
.withMethod(HttpMethod.GET)
.withExpiration(expiration)
val url: URL = s3Client.generatePresignedUrl(generateSignedUrlRequest)
preSignedUrl = url.toString()
Logger().logInfo("AWS", "getImagePreSignedUrl $preSignedUrl")
}catch (illEx: IllegalArgumentException){
Logger().logInfo("AWS", "getImagePreSignedUrl err ${illEx.message.toString()}")
}
return preSignedUrl
But after releasing the app to google play it gives me the below warning
Your app(s) expose Amazon Web Services credentials.
Please advise me on how to achieve this in the app with or without storing AWS key and secret in the app?
Solution 1:[1]
A native Android app cannot use most of the ways that other apps can use to read creds. For example, a Native Android app cannot load credentials from the [default] credentials profile in the shared credentials and config files ( that can easily be done using an app like a Java Desktop Swing app).
Using a StaticCredentialsProvider is a reasonable way to solve it. This does mean that you have to specify your creds in the code when using this provider.
Solution 2:[2]
I have a crude idea.
You will need, API Gateway, AWS Lambda and SSM Parameter Store/Secrets Manager.
- Create an API Gateway. Secure incoming requests by providing API Keys for your Android App.
- Trigger a Lambda function to retrieve Credential stored in Secrets Manager or Parameter Store.
- Encrypt the data using a private key available to your application.
- Send the encrypted Secret and Access Key in the response.
- Decrypt the data on your application.
This is technically a burden and you should do it once when your application initiates and then store the credentials in Shared Preferences and stop the retrieval until you have some values in preferences.
Or it is up to you how you want to manage it.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | Himanshu Rawat |
