we are developing an android library, that will communicate with our backend. This library will be distributed to our clients, allowing their applications to send data to our servers.
Each library should communicate in a secure way, with client credentials (token and so on).
Where would be the best place to store that token? Maybe in manifest? Plain text file in a single folder?
I want to be as much transparent I can. Client should download my library, download credentials file, and all should start running smoothly.
Any tip?
Thank you so much
From the official official documentation
Handling Credentials
In general, we recommend minimizing the frequency of asking for user
credentials—to make phishing attacks more conspicuous, and less likely
to be successful. Instead use an authorization token and refresh it.
Where possible, username and password should not be stored on the
device. Instead, perform initial authentication using the username and
password supplied by the user, and then use a short-lived,
service-specific authorization token.
Services that will be accessible to multiple applications should be
accessed using AccountManager. If possible, use the AccountManager
class to invoke a cloud-based service and do not store passwords on
the device.
After using AccountManager to retrieve an Account, CREATOR before
passing in any credentials, so that you do not inadvertently pass
credentials to the wrong application.
If credentials are to be used only by applications that you create,
then you can verify the application which accesses the AccountManager
using checkSignature(). Alternatively, if only one application will
use the credential, you might use a KeyStore for storage.
So using AccountManager seems to be the best option for storing credentials.
You can also use the SharedPreference but it's risky cause on rooted phones it is possible to access the preferences file of an app.
Related
I have read about Parse server which was created by facebook , but I think there are serious security issues.
I can decompile other people apk and get Parse master key, appId and then I can connect this people parse server from my own application and can do whatever I want to do with his data which very dangerous
Even I can make while(true)loop and insert infinite data to the parse server.
So how can I connect any API in Android Studio securily?
You shouldn't put the master key anywhere publicly available. If it's in your APK, you're doing something dangerously wrong. Master key should only be an environment variable on your server.
Sure, you could get anybody's app id and client key (if they added one) by decompiling, but that's the same with basically any API. You need to use the security tools provided by Parse, namely CLPs and ACLs. You shouldn't have any data too sensitive on your server at all. I.e., you never need to store a user's actual payment information, you should use a payment API, pass any information needed to them directly from clients, and store the tokens they give you. I.e. with Stripe, there is a "public key" that is used on the client to talk to their secure server, pass credit card info, and create a card token, and you pass that card token back to your server, which can use the secret key, which should absolutely never be put in a client app, to create charges and things.
CLPs and ACLs restrict access to your objects. CLP (Class Level Permissions) are used to restrict entire tables. They have a cool thing called Pointer Permissions, so if an object has pointers to a user, you can set it to the user set on that field can access their objects. You can restrict public access so you can only get an object with the id, but not find it in a query. You can completely restrict read access, and you should restrict write access on most classes. Business logic goes on the server, you can verify a session token to make sure a user should be accessing an object and then use your master key to actually do necessary updates.
Parse-Server has all of the security implementation you need to protect your user's data. You just have to implement it properly. If you don't use CLPs and ACLs, anyone can decompile your app and get your entire database.
Also, Parse wasn't created by Facebook. It was acquired, then shut down and open sourced about a year or so later.
The Application ID is not a security mechanism and you must not ever use the master key in public applications as it allows you to bypass all of your app’s security mechanisms. It's a big mistake to store master key in the app.
Security must be provided to Parse Server by Class Level Permissions and ACLs (and all connections should be made with HTTPS and SSL).
In my experience, Class Level Permissions should rarely grant Public access (default behavior when creating a Class in Parse Dashboard). I only use Master key for testing purposes and to do some queries/savings in afterSave triggers and cloud functions.
I recommend reading the Parse's Security Guide to understand a bit better how to build a secure Parse API. Here is an important fragment that backups my answer:
The master key, on the other hand, is definitely a security mechanism. Using the master key allows you to bypass all of your app’s security mechanisms, such as class-level permissions and ACLs. Having the master key is like having root access to your app’s servers, and you should guard your master key with the same zeal with which you would guard your production machines’ root password.
You can store your API keys, Secret keys or any other important key information in .C file.
For that you have to use NDK.
You can follow this link for how to use the NDK to secure your file. You can also find GitHub demo app link at the bottom of the page.
Note: If you are using NDK it will increase your APK size.
I'm trying to work out the best solution for a particular situation I'm in, and am having trouble working out the best option. It's a tricky setup, so might be a fun challenge for you Android experts! Here's my situation:
We have two Android apps already on the Play Store, and are working on another right now.
The two released apps are signed with the same keystore, but do not currently have a sharedUserId set in their manifest files.
The two released apps store a user's oAuth token in SharedPrefs, some product/content data in an SQLite DB, and some audio/video content in external storage (using getExternalFilesDir).
The apps are all separate oAuth clients/applications of our server (i.e. they all use different client ID and secret keys).
Our server is setup to only allow one oAuth token per oAuth application (i.e. Android app). e.g. if a user logs in to app A on one device, then logs into app A on another device, the first device's token will be invalidated and the app will receive a 401.
We've successfully implemented a single sign-on system on iOS by enabling shared keychain between the apps. If an app detects that another app in the group has a valid oAuth token, it can send that to our server and exchange it for a valid token for that app.
In the iOS version, we wanted to ensure that the apps didn't need to know about the existence of the other apps using hardcoded values per-app (e.g. if we release a new app in the future, other apps don't need to be updated to share/receive tokens with it), so we created an entry in the keychain containing an array of bundle IDs that had valid tokens, that all apps could access. When an app successfully logs in or exchanges a token, they add their own bundle ID to that array. Any newly installed app could find a bundle ID from that array, and use that it as a key for loading the token details for that app, which it would then exchange for its own fresh token.
We want the token exchange to be automatic and not require input from the user.
I hope that all makes sense!!! Please let me know if not.
I'm now trying to work out the best method for storing oAuth tokens (plus some additional data such as email address to go with it) on Android so that other apps owned by our account can access them in order to exchange for a fresh token.
I've looked into using the following, but am unsure of the best route:
SharedPreferences along with sharedUserId
AccountManager (https://developer.android.com/reference/android/accounts/AccountManager.html)
Android Keychain (https://developer.android.com/reference/android/security/KeyChain.html)
ContentProviders
The problem with option 1. seems to be that setting the sharedUserId after first release will lose access to all of the data (see http://java-hamster.blogspot.jp/2010/05/androids-shareduserid.html). This is not a nice thing for our users.
Option 2. (AccountManager) could be a good option, but if we want to store the tokens separately (per-app), but want any other apps we make to access their tokens, I'm not sure how we'd do that.
Option 3... is it possible to do what we need with Keychain?
If I understand correctly, option 4 would need each app to have its own ContentProvider? I'm not sure how that would work for our requirements.
If anyone has gone through this kind of situation and could share some insights and recommendations, I'd really appreciate it!
ContentProvider is probably your best best. I won't be able to provide the whole code for you to do this, but this is generally how I see it working:
Each app creates a content provider that exposes their own API token;
Each app tries to acquire and query (sequentially until successful) all the other content providers before requesting a login;
If app X is able to acquire and retrieve the token from app Y (via Y's content provider), then store it in app X and use it;
Side notes:
This is very sensitive information, so you should enforce security. Your content providers should only be accessed by other apps signed with the same key, they should have only read permissions and you should create your own custom permission as well.
The content provider does not need to access an sqlite database. It can access whatever your using to store the token (which I hope is stored in a secure way, but I'll leave that to your own judgment)
Useful links:
How to create a custom content provider
How to secure your content provider
Example of content provider that retrieves data from shared preferences;
AccountManager is meant to solve the exact problem that your are commenting. Here is a good tutorial to work with it:
http://blog.udinic.com/2013/04/24/write-your-own-android-authenticator/
Just be sure that you sign all your apps with the same keystore, because this is the only thing that might complicate things (a lot).
Using preferences will lead you into a problem as all that you store in the main thread is not guaranteed to be there in a Service (like a SyncAdapter). There used to be a trick for this in the form of flag (MULTI_SERVICE) but was deprecated in api 23.
ContentProvider is of course possible (its too generic) but AccountManager will help you to cover the corner cases related from refreshing tokens and other interesting stuff.
Adding the AWS access key and secret key directly in app code is definitely not a good approach, primarily because the app resides on the users device (unlike server side code), and can be reverse engineered to get the credentials, which can then be misused.
Though I find this information everywhere, but am unable to find a definitive solution to this problem. What are my options? I read about the token vending machine architecture for temporary credentials, but I am not convinced that it is any better. If I can reverse engineer the secret key, then I can reverse engineer the code which requests for temporary credentials. And once I have a set of temporary credentials to access S3, I am as good as if I had the key. I can request the temporary credentials again and again, even if they expire pretty quickly. To summarize, if an app can do something, I can do the same as a malicious user. If anything, the TVM can be a bit better at management (rotating credentials, and changing key in case of breach, etc.). Please note we can put the same access restrictions on the secret key, as we plan to do in case of TVM temporary credentials.
Additionally, if Amazon doesn't want people to use the secret key directly in the App, why don't they block it in their SDK, and enforce TVM or the correct solution. If you will leave a path, people are going to use it. I read several articles like these, and wonder why?: http://blog.rajbala.com/post/81038397871/amazon-is-downloading-apps-from-google-play-and
I am primarily from web background, so my understanding of this may be a bit flawed. Please help me understand if this is better, and whether there is a perfect (or may be good) solution available to this problem.
PS: Is there a rails implementation of TVM?
Embedding S3 keys in App code is very risky. Anyone can easily get that key from your app code (no reverse engineering or high skill set required), even if that is stored encrypted it is still compromised just that someone need to try harder (depending on how do you encrypt).
I hope that you understand the advantages of using temporary credentials to access Amazon (S3 etc) resources (mainly security + some others like no app update etc). I think you are more confused about the process to get the temporary credentials from TVM and how that is safer than embedding keys in code.
Every client using TVM first need to register with the TVM server implementation hosted by you. The communication between App (using TVM client) and TVM server is over SSL.
First the app register with TVM by providing UUID and a secret key. Please note that the secret key is not embedded in App code (which I think is main reason for your confusion) but generated randomly (using SecRandomCopyBytes which generates an array of cryptographically secure random bytes) at the time of registration (and hex encoded).
Once the device is registered successfully with TVM, the client TVM store the generated UDID and secret key in a storage called Keychain in iOS and Shared Preferences in Android. The keychain in iOS is the shared storage provided by iOS to securely (encrypted) store information (mainly keys, password etc).
After registration and UDID/Secret Key storage, App can get the token from TVM by sending the UDID, cryptographic signature, and a timestamp. The cryptographic signature is an HMAC hash generated from the timestamp using the secret key. The TVM can use the UDID to lookup the secret key and uses it to verify the signature. The TVM then responds by sending back temporary credentials, which are encrypted using the secret key (uses AES). The application decrypts the temporary credentials using the key and can then use them to access any AWS services for which the temporary credentials are authorized. Eventually, the expiration time of these temporary credentials will be reached, at which point the application can get the fresh temporary credentials, if required.
I am not sure how signed URLs relate to TVM, because I don't understand the concepts 100% but signed URLs really solved the problem for me. I needed a mechanism that would feed web app and mobile app data without allowing for misuse of the credentials. Putting the key in the code is indeed a very bad idea as it may generate a huge bill for the company.
After 3 days of extensive research, I found a simple and, what seems to be, a reliable and relatively safe solution: signed URLs. The idea is, that a very light-weight back-end can generate a temporary URL that will grant the user access to the specific resource for a limited time. So the idea is simple:
the user asks our back-end with a Rest call that he wants a specific resource
the back-end is already authorized with AWS S3
the back-end generates a temporary URL for the user and sends it in the Rest response
the user uses the URL to fetch the data directly from the AWS
A plug-and-play Python implementation can be found here and with a slight modification that I had to use: here.
Of course one more thing to figure out would be how do we authorize the user before we know that we can grant it the URL but that's another pair of shoes.
You should ideally use Cognito Identity for achieving this along with appropriate policies. It should be used with S3TransferUtility and S3TransferManager in iOS and Android SDKs. That would allow for background uploads and downloads as well. Cognito vends temporary credentials for access to AWS resources and is free. Also, you could federate it using UserPools or providers like Google, Facebook if you want secure access.
Thanks,
Rohan
I've read many, if not all, answers to previously asked questions about the same topic, but questions themselves are not exactly about my case.
I have an OAuth 2.0 server running. It has an endpoint that provides access tokens to users. Programs and websites requesting the access token may or may not be owned by me, in other words, I may add a tool for website users and locate it on the same or neighboring website and my users may create an app and with their API key request access to user's data. Now I am developing the app that will operate user's data.
I realize that storing the API secret on the device is not a good solution. I have read about creating an end-point to which I make request directly from the app and then the endpoint makes API requests, but the endpoint will have to exist on the same host and probably server as OAuth server.
Is there a way to authorize mobile application to access user data when I am in controll of the application and the OAuth server? Should I create a separate end-point? Should I pass it device ID and/or any other information?
P.S. I know that plain old authorization would work here, but then what if some user wants to create his own mobile extension (not allowed currently for security reasons)? Also, current system has a button that is recognized by many people and they know what exactly will happen after clicking it. With the app, it may be an issue when the user sees a login dialog instead of the "Login with *" button. I really hope there is a clever solution to this.
Your concern is spot on. Your API Secret should not be stored on the device.
However, I am not sure why you would be concerned to build a separate endpoint, since OAuth 2 has a authorization flow for these use cases.
https://www.rfc-editor.org/rfc/rfc6749#section-9
In your use case, I'd suggest using the implicit grant flow to fetch the access token and store that on the local device. There would be no refresh tokens and the access_token can have an expiration date. Of course, the token on the device can be compromised, but the damage will be limited to a particular user and not the entire application.
If this level of security is not acceptable, then you can look at splitting up your API Secret in different parts of your app and then assemble it at run time in your app.
We're currently in the process of implementing OAuth2 to secure our new API and not sure how to securely provide required functionality. We need to allow the following from a mobile device:
Immediately after downloading the app the user is able to take a picture and submit it without having to first log in.
While we want to allow anonymous user access, where a user does not need to log in or register to use certain functionality, we do not want to allow unauthenticated access to the API. This would normally be accomplished using the client credentials authorization flow to obtain and app access token, however this requires knowing the client secret. From what I've read, a mobile device is not considered a trusted client and should not contain the client secret, and hence should not be able to generate an app access token on its own.
We've come up with a few options to accomplish this requirement, but would like some input on them:
Embed the client secret in the app. Doesn't seem ideal from a security standpoint, but maybe we're missing an obvious way to secure it? We're targeting at least iOS and Android.
Generate an app access token offline and embed that in the app. Still not very secure, but at least the secret isn't exposed.
Allow access to certain functionality using only the client ID instead of an access token. This may be the simplest, but it introduces an inconsistency and requires multiple ways of authenticating the client.
Build and use a companion web app to generate app access tokens for the mobile app. On the surface seems like a winner, but now you have to secure access to the companion app!
How would you securely authenticate access to an API using OAuth2 from a mobile device without requiring the user to first log in?
Agree with the comments on the Q. Either:
1.) Use Client Credentials grant type in OAuth 2 - with an embedded secret in your App. Understand that this isn't super secure and someone will reverse engineer it eventually. Ideally each client would get a unique secret - so you could revoke a client if they're abusing its use.
2.) Live with that API being open - thereby not requiring an OAuth 2 access token at all. Maybe that API would be known only to your app - but again, it would only be a matter of time before someone reverse engineers it.
My group is having a similar discussion. Users can get the app and browse a catalog without having to sign-in. The catalog and other data is accessed via an API and we would like to force users to have an access_token for all calls.
Our current thinking is to
Always force the App to exchange a common clientId/secret for an access_token. So the app would get an access_token even for anonymous users. This would be via the client_credentials oAuth flow.
If the user signs in, use the oAuth password flow. They would pass in clientId, secret, username, and password. We would additionally allow them to pass in their anonymous token so that we could transfer any history from their anonymous session.
So for example...
access_token = api.oAuth.client_credentials(clientId, secret)
catalog = api.getCatalog(access_token)
authenticated_access_token = api.oAuth.password(clientId, secret, username, password, access_token)