How to secure service account credentials in an Android application? - android

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.

Related

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.

Android WebView wrapper authentication methods

I'm wrapping a Rails mobile website with an Android WebView wrapper, but it's also supposed to be available through the browser as well. The website is using Google/FB OAuth authentication, but that's not essential.
When the wrapper is used, I wanted the user to be already signed in with its primary email.
Are there any secure methods to achieve this? Something which will not allow using this method in the browser?
I was thinking about sending some kind of checksums / secure tokens but this could be easily reverse engineered.
Would the authentication with device id and android id be enough? I mean, these are available publicly for other apps so I guess possibly not. Maybe there is something that is unique to the app instance and private?
There is nothing automatically secret in an instance of an Android app that your server could verify. Using Google/Facebook OAuth login is a reasonable choice.
You can use the Facebook SDK for Android to allow the user to log in using their Facebook account, and as a.ch. mentions in the comment you can do the same with the Play Services SDK to log in via their Google account.
In both of these cases, this works because there is a local broker app (Facebook, or Google Play Services) that is trusted by the identity server (facebook.com, or google.com). The broker app has the user's credentials, can verify the identity of the app that is requesting access, and can display a view where the user can approve/reject the request. Once the identity server knows that the user has logged in on the device, knows the identity of your app, and knows that the user approved the login request, it can safely send back a token to your app via the broker. That token allows whatever permissions your app requested and the user approved.
Your WebView can then include that token in an initial request to your rails server, which checks the token with Facebook/Google. From this point, the code should look similar to the existing desktop web, at least with respect to user authentication.
You can download the Facebook SDK for Android from https://developers.facebook.com/android/, and you can get the Google Play services SDK in the Android SDK manager ('android sdk') under Extras. Both have tutorials to help you get started.

Should I use GoogleAuthUtil to call my backend to secure the communication even I don't need to use the logged Google user?

I am writing a game where the user sends his score to a server I maintain.
I want to secure that the score has been submitted from the game app, not from a curl request or other mean of HTTP request not started by the app.
I read this entry in the Android developer blog and I thought I needed to implement this, but I'm not sure.
Along with the score, the user will send a player name typed in an EditText as his player name. This means that the users are identified with a name they choose, NOT their Google account username.
Neither the client nor the server need to access the Google user account at any time.
Is this meant to do what I want, or is it used only to guarantee that one HTTP has really been performed from the device of a specific Google user account?
What should I pass as email to the getToken(email, scope) method?
My users won't have an Android AccountManager account.
After more diving I have concluded that:
The email that GoogleAuthUtil#getToken() expects is the email of the user's Google account. This can be programmatically retrieved via the AccountPicker class. This is explained here.
I could use this method to authenticate my server calls, but I think that if I do not plan to use the user Google account information and I don't plan to use the Google Cloud endpoints, I could work with something simpler.
Moreover, If you I used this to authenticate the calls I would depend too much on Google, not being able to release the app in the Amazon market, where the user may not have a Google account (Kindle FIre).

Authenticated communication b/w Android app And GAE server using OAuth2

New to OAuth2. I am writing an Android app that communicates with an App engine server application.
The app needs to authenticate itself with the server on behalf of the user, using Google account info of the user. The server needs to retrieve the user's basic info and create an account . That's the easy part and I know how to do this.
Furthermore, the Android app will also have the user authenticate himself/herself using Oauth2 and retrieve basic user info using Google account info of the user. I can do this as well.
This is where I need help Assuming the previous steps have been completed successfully, how can I use the Android app (where the user has logged in) to communicate with the server securely using the user's credentials.
Any ideas or am I missing something obvious?
The Android to App Engine OAuth2 communication is documented in this answer:
google app engine oauth2 provider
Using OAuth, 1.0 or 2.0, doesn’t matter in this, leads to the app obtaining an access token - then based on the API of your server, you pass this access token with requests instead of login and password. I guess the way to attach the access token string to URL requests may be slightly different between different APIs, see the documentation for yourself. Or if you are making the server app at the same time, then you need to figure out your way to do so (like sending a HTTP header Authorization: OAuth access_token=abcdefgh….

Android APP that consumes a webservice how to authenticate users

I'm developing an android app that consumes a webservice that I will develop too (I'm thinking in using a RESTFul webservice)..
and I want to secure the connection between the app and the server but I need to authenticate users too..
My problem is in the last part, to secure the connection I think the best way to do it is to use SSL (https), am I wrong?
I don't know what's "the best way" to authenticate users, to make sure that a user cannot consume the webservice as another user..
I have some ideas, like using a authenticate(login,pass) method on the webservice that returns a token.. And for any operation that requires authentication the user would need to pass that token as a parameter.. The thing is, is this a good way to do this? whats the most common technique used to auth users in a situation like this?
If a token based auth is a good idea how should I generate the token?
Sorry for this long text..
Any help will be usefull
Thanks
Make sure you understand a trendy standard like OAuth before you go down that path. Most OAuth flows are centered around a user logging in to your server through a web browser. This can lead to pretty bad user experience for a mobile app. The standard does allow for alternatives. Here's a decent introduction.
You could also use an existing identity provider like Google, Facebook, Twitter, etc. instead of implementing your own authN/authZ. On Android, you can ask for a Google auth token using the AccountManager. This usually works because the user needs to be logged in to their Google account to access the Android Market. Anyway, this will prompt the user to grant authorization to your app. You could then use the Google auth token to login your user to your service with your own token. The login would essentially be your server verifying the Google token is valid (by contacting Google's servers) and then issuing its own token to be used for calls to your web services. If you don't like Google, you could use the Facebook SDK, etc.
As for what to use for tokens... The OAuth spec has stuff on that as well. You could do something as simple as a random string or something as complex as encrypted SAML assertions.
You should implement a token based OAuth, which will require the users to log in once, and then permanently have access.
You can use Google App Engine which already provides user authentication services for you (your Android users most likely already have google accounts) But this is only one of many options.
You can also look into Amazon's Identity Access Management (IAM) which will allow you to manage the users who have access to your web service, and authorize them accordingly.
I think the best way to do it is to use SSL (https), am I wrong?
This only prevents certain types of malicious use, but not everything. There is still nothing to prevent people from accessing your database on the phone, and retrieving credentials that way.

Categories

Resources