How to use AWS S3 credentials in android for uploading contents - android

I am using AWS S3 to upload and store contents in my Android application. I am using the below code in a java file:
AmazonS3Client s3Client = new AmazonS3Client(
new BasicAWSCredentials("XYZ",
"ABC+wktN"));
But this seem to be easy to retrieve (even if the apk is signed!). I tried using progaurd but that crashes app on some mobiles devices (especially this AWS part).
Is there any approach where i can hide credentials in Code without anyone being able to retrieve it? Or has anyone used any other method? One option is to upload to a intermediate server and the server uploads it to AWS S3, but thats an extra hop. Another is make the app get credentials from server through an URL call instead of having the credentials on mobile, but if a hacker can get the credentials directly he can get the URL as well and get the key.

Amazon Cognito can help you solve the problem. You can use it to deliver temporary, limited-privilege credentials to your application. With Cognito
you don't have embed long lived credentials inside your app
you can retrieve temporary credentials from Cognito. In case credentials are intercepted, they are valid at most an hour (configurable).
you can attach access policy to the credentials to limit what resource the credentials can access. See Understanding Amazon Authentication Part 3 Roles and Policies.
Cognito supports integration with 3rd party identity providers like Facebook, Login with Amazon, etc. You can force customers authenticated before accessing your resource
Cognito also supports developer authenticated identity, so that you can build your own backend to authenticate customers.
You can find additional information their blog http://mobile.awsblog.com/blog/tag/amazon-cognito and the developer guide http://docs.aws.amazon.com/cognito/devguide/identity/.

Related

How to grant access to android app users for AWS S3 Objects?

I have a bucket in Amazon S3 and I have Lambda functions that generates JSON files for this bucket. I am using the S3 files in my mobile app. Until recently, I gave public access to these S3 files for simplicity. But now I want these S3 objects to be accessible with a simple authentication. I’ve examined all AWS tutorials but couldn’t find an easy way to implement this. I don’t want to use Cognito service since my app doesn’t need authentication and since my S3 files are not user-related, they are used for app. I want these S3 objects to be accessible by http request to a url which includes simple key like this:
https://s3.eu-central-1.amazonaws.com/<bucket name>/<object name>?<key>
where key can be a combination of region, aws access key, secret access key or other values of the user that i define (I am using Retrofit to fetch json data from S3 bucket) I’ve looked at the presigned url option but an example for android-sdk doesn’t exists there, and most of the methods that can be used for this purpose are deprecated. Isn’t there an easy way for this? Or should I host my json files in other service/place?
If you say no to Cognito then you are just complicating things for yourself. This is exactly the case where you want to use Cognito. The fact that you don't require your users to authenticate and that the S3 content is not user specific doesn't mean that Cognito is not suitable in this scenario.
All you have to do is to create Cognito identity pool and choose to support unauthenticated entities. Create an IAM policy that allows reading from that specific S3 bucket and let unauthenticated users to assume that IAM role by attaching it to those unauthenticated entities.
Authentication then happens automatically during the initialization of SDK in your application. That is all that you need to do to allow access to that S3 bucket only from your application.
And you get access metrics even for unauthenticated users as a bonus. And if you later decide that you want your application to support authentication as well, then you don't need to change almost anything in your setup.

How to secure service account credentials in an Android application?

I have an android app which communicates with Google cloud api services like speech to text, translation, NLP etc. The application is using a service account to do this and the private key file is stored in the application itself. I understand that is a bad practice as anyone can see it using dissembler but I am not sure where else to store it for an android device.
The following post suggests to store this file on a build server:
https://brightinventions.pl/blog/securing-your-google-service-account-key-in-builds/
However, I think that it does not fix the issue as the service credential file is getting included in the publish package.
Please let me know if you can think of a solution.
Do not embed service account credentials in applications. Service Account credentials have a permanent lifetime which means you will be breached. You can delete service account credentials, but then you will have to re-release your application.
You have several options:
Implement Google OAuth so that your users authenticate with Google Accounts. When authenticating use the correct Google OAuth Scopes to provide temporary permissions.
Implement temporary access tokens. Your users will connect to your website, authenticate and your code will give them a temporary access token created from service account credentials. This access token will expire. The default is 3600 seconds but you can control this.
You users will make all requests thru your website API's. You control authentication of the users. Your website code then makes the API requests on behalf of the users. This is not an ideal solution as all traffic goes thru your website (Compute Engine, App Engine, etc.) and you will pay for that bandwidth.

Authenticate with web server before uploading/downloading file to AWS S3

I want to create an android application and use AWS s3 as a storage service to allow the user to upload and download files. I have studied something about S3 REST service, which can help me achieve the same, after configuration of IAM Role for Bucket etc.
Now thing is, I want only the registered users of my application/ with access control configured at my web server(username/password) should be allowed to upload/download the file and not anyone with only app access should be allowed.
Look the link below as well, to have some idea about AWS S3 upload file using REST
http://www.tothenew.com/blog/file-upload-on-amazon-s3-server-via-rest-api-call/
Putting simply, in addition to that described in the link above, I just need the answer to the following questions:
1) How to allow only registered users?
2) Is it good practice to hard code AWS S3 secretKey etc in the production application.
3) Does hardcoding these values in my app could lead to a scenario where even an unregistered user of my application could be able to upload/download the file to aws s3?
All suggestions are welcome, if-if they solve part of the puzzle, as I am completely unaware of the solution
It would be very helpful...,
Thanks in advance,
For sure it is not best practice to hard code secret keys inside your codes..
Now if you want to separate the authorized and the unauthorized users one AW services that does this job and more is AWS Cognito . You can find a lot in the aws documentation https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-console.html
A few things for Cognito :
You have Amazon Cognito User Pools tha provides :
Sign-up and sign-in services.
A built-in, customizable web UI to sign in users.
Social sign-in with Facebook, Google, and Login with Amazon, as well as sign-in with SAML identity providers from your user
pool.
User directory management and user profiles.
Security features such as multi-factor authentication (MFA), checks for compromised credentials, account takeover
protection, and phone and email verification.
You have Amazon Cognito Identity Pools (Federated Identities) that provides :
Users in an Amazon Cognito user pool
Users who authenticate with external identity providers such as
Facebook, Google, or a SAML-based identity provider
Users authenticated via your own existing authentication process
This how it works in my application
Ask user register/login using aws cognito
deploy an api via api gateway that acts as proxy for S3 services
For the api , apply AWS cognito as Authorizer in api gateway
This however has a limitation on size of object
The option I have tried is use signed urls, and this is spit out by back end application upon registered users access requests.
My implementation includes below
1. Client requests signed urls using an api with a lambda implementation
2. Lambda generates signed urls and passes on the response.
3. while creating signed urls, key/id are used from a parameter store (see EC2 parameter store) secured against role and with a KEY.
I think from your use case , EC2 parameter store (instead of database) should be sufficient to securely keep secretes.

Generating pre-signed URLs for AWS S3 access from mobile app

This has probably been delved into multiple times on SO but I still can't get my head around the flow here. Can someone please help throw some light here as to what I might be missing!
I am building a mobile messaging app, with the backend chat server in Erlang and photos getting stored in AWS S3. I want to ensure that when a user sends a photo to a group, the same is downloadable only by the said group's members and no one else.
From what I understand, I need to have pre-signed URLs (of the uploaded photos) distributed to the chat recipients (i.e. group members) so that they can download the same directly.
My question is: How do I generate these pre-signed URLs? And what role does AWS Cognito have here? Should I build a new web service that can be queried by the mobile app? So this web service would call Cognito's getIdentityId() and use the response (along with the bucket name / key passed by the mobile client) to generate the pre-signed URL, which it would then pass back to the mobile client, which can then distribute this URL to the group chat recipients?
Or should the Cognito credentials provider and the user pool ID be included in the mobile source code and the iOS / Android app itself should generate the said URL?
Apologies for the rather long rant!
The cognito credentials are used to sign the pre-signed URL which is generated by the SDK. If the pre-signed URL is not signed with valid credentials the get request for the download fails.
Then cognito pool id has to be present in the app which fetches temporary credentials for getting access to AWS resources.
Thanks,
Rohan

AWS Cognito vs IAM role in Android APP for security aspects

An app of mine in the android playstore (let's say >1.000.000 installs) collect some anonymous statistics. I want to store and work with these statistics on an amazon EMR cluster.
Currently I use AWS Cognito for creating Unauthorized access for Uploading the data to S3/Firehose. For saving money I thought of changing this procedure to use a hardcoded IAM user, which only able to upload the data to FH/S3. I don't need the identification of each user.
What disadvantages should I expect in terms of security?
Cognito federated identities is 100% free. Switching to an IAM user won't save you money.
Per the pricing page: "Using the Federated Identities feature for authenticating users and generating unique identifiers is always free with Amazon Cognito."
I think if they somehow get access to your sourcecode they can upload data to s3/firehose . Actually I am in the same kind of dilema only I dont have an app on appstore yet but since the IAM i am using only has read access to a AWS service I dont really see issue with it. because If I am correct AWs does charge for every token refresh after 50.000 MAU if you use Cognito

Categories

Resources