We're developing a JSON REST API in Rails to be consumed by an Android application, which we are also developing. Is there any way to secure the API such that it can only be used by our specific Android application?
The API is read-only, and does not involve any kind of user-related or otherwise sensitive information. But to the extent that is reasonable we'd like to prevent abuse and restrict its use to only our app.
I could easily add an authentication token to the API and distribute it with the app, but:
We'd probably have to move the API over to SSL, if we use BASIC auth.
It's probably trivial for a determined person to open up the Android APK binary and uncover the auth token anyway.
The situation seems analogous to a café posting their WiFi password on the shop counter- you have to give the secret out to everyone who wants to use your service, so it almost seems pointless to have it in the first place.
What's the most reasonable approach to take?
Wanting to secure a probably public undocumented API so it can only be accessed by one application, means you want to stop people from using your API who are determinate of using your API.
Meaning people who would try everything possible to use your API.
If this is not the case adding a Auth token won't be trivial but at least a big stepping stone for people who stumble upon your API. And not a very bad idea to implement this.
Because this authentication isn't user based but application based and you don't want authentication to rely on user input. The request must be purely done so by the application.
Meaning you will have to do so anyway(adding hardcoded token). Only you make it very very difficult for a determined person to uncover the access and request tokens and the methods.
It depends on the situation, but I would go for the SSL and hardcoded token.
Some extra security:
Release an access token to the application which only need to send a
request token periodically. Meaning less chance people intercept the
hardcoded request token, but a session based access token which
expires. Maybe just do this once for every application install.
Encode this request token before sending it through the air. Meaning
people have to decompile your app.
Obfuscate code (make it more difficult to decompile).
Related
I'm looking for your input in authentication to a rest api related question.
Now Imagine the following scenario:
I have an android app that wants to use resources provided by an public API called MAIN_API (which i have no control over) that has a universal API key. The API key grants access to risky actions such as deleting records.
Now i want to allow the users of the app to have a very limited access to the API resources, but i want them to be able to use the application anonymously ( no credentials of their own).
I figured that the best way to approach this is to have another server that would contain the API-key and would provide the means for the limited access for the MAIN_API (for example PROXY_API would only call simple query endpoints). The actual mobile app would call this API. Call it PROXY_API for the purpose of explanation
Do you think this approach is enough to stop malicious usage of the MAIN_API? Do you think it would be beneficial to generate some sort of application credentials getting an access token from the PROXY_API?
To provide basic authentication to a web service is quite simple and will depend on the technology stack you are using on the server.
I'd recommend that if you need to both grant users and client applications access to resources to use an authorization mechanism such as OAuth. There are Opensource OAuth server implementations available. Though the OAuth server is a standalone component, securing your resource server to check authorization against the actual OAuth server may depend on your technology stack.
If you are not very knowledgeable about security, and want to control access to your API/Webapp using OAuth, I'd recommend you a service like Stormpath, Auth0 or 3Scale. They first two offer free accounts and can help you kick start your product.
My web server has a REST API. I need to add user authentication to my app, and my thought process behind it is this:
Get the user's username and password from the app form
Encrypt the password and Base64 encode both the username and password
Send the data to the REST API over HTTPS
Web server verifies credentials, returns errors or success
Is this secure? I see a lot of mentions of OAuth2. What is it? What does it do better than my process?
The fact that you used the word "encrypt" for the users password instead of "hash" demonstrates you have fairly limited knowledge about this. This will almost certainly result in you messing up your authentication procedures somewhere along the line and put your users private information at risk.
A really important point about OAuth2 is that it can be used with many existing third party providers (Google, Facebook, Twitter, etc) with minimal effort from you.
You don't need to do anything to store credentials or even authenticate users. The third party takes cares of all of this and simply provides the client with a token (long random string) which is then passed to your server. Your server then talks to the third-party server to make sure the token is valid (and gain any info you need, like the users' name, email address or other information).
You really should consider using it if you can. The big companies put a lot of effort into securing their authentication methods and you gain all of that by making use of it.
A final nice point is that users don't need to create and remember credentials for (yet) another account.
Google has some docs to get you started and includes an OAuth playground to test how it works in practise.
A very basic explanation of OAuth2 is that the user will log into your system, with it encrypting both username and password before sending it, then if it gets authenticated, it will send back a token to the user.
Thereafter, whenever the user tries to contact the web server, it will send this token along with each API call. This is how it makes sure that non-authenticated people can't access your web server.
So basically your current method includes parts of the OAuth2 standard, but not the most important part (The token).
In your situation, how would you stop non-authenticated people from accessing your web server? If the project is small, then the risk of this is not that large.. But for larger companies, this is a real threat that needs to be dealt with.
You should really try to understand the difference between encryption and hashing before providing an authentication portal for your users. There are many different hashing algorithms you can use. I've personally used BCrypt in the past and I have a related SO Question about it as well. You can find implementations of pretty much all the popular algorithms in pretty much all the major high level languages these days.
Obviously if you don't want to do all that you can use an OAuth provider, who will take care of all the hard bits like storing the passwords securely, protecting the database and all the other security aspects for you. There are many reliable OAuth providers, Google, Facebook, Yahoo, etc. etc.
One thing to bear in mind would be the environment in which your app is hosted. OAuth does depend on having a connection available to the OAuth provider's servers every time a user wants to access your app. So, if you are behind a corporate firewall or similar which may block access to websites like Facebook, this might be a big problem.
I personally prefer token based authentication for my API projects. If you're not familiar with token based authentication you can read this SO Question and this link.
The general concept behind a
token-based authentication system is
simple. Allow users to enter their
username and password in order to
obtain a token which allows them to
fetch a specific resource - without
using their username and password.
Once their token has been obtained,
the user can offer the token - which
offers access to a specific resource
for a time period - to the remote
site.
I've been doing a lot of search about secure my api for mobile apps for Android or IOS.
Almost all examples tell user provides an user id and password somehow in a exchange for a token.
But how to prevent someone else to consume my api without my consent?
Face the following scenario:
I expose an API,
I develop, then, an app for android to consume it,
I develop, then, an app for IOS to consume it.
Other developer performs a rev. engineer in my app, creates his own app and starts to consume it without authorization.
How to prevent that?
Short answer: you can't.
Little longer answer: If you know what you are doing you can always reverse engineer a given application and use its api. You can only make it more difficult and time consuming, using authentification via tokens and device ids or usernames is a good first step. Apart from that: why would you want to close your api to outsiders? If your server code is written well there is nothing to worry about.
You can maybe secure your API on a legal basis and sue developers who use it, but that is a completely different topic.
Some clarification regarding securing the API and securing content via the API. Assume you create a server where you can send user/password and receive a token if that combination was correct. For the account-page you send said token over and the server verifys that that token is valid and returns your account page. You secured the actual content of the API. That is obviously very possible and almost a must-have unless you have no user-specific data. But still everybody can send the exact same initial request from their custom app, sending a user/pass and again receive a token, etc. You cannot really prevent the request itself or even determine that it was not send by some service not authorized by you. You can send some hashes along the request to add some security by obfuscation, but since your app has to compute them, so can the reverse engineer.
Yes, login api are open but they return a token only on successful match in your database. You should focus more on security of your data than unknown hits at your api.
SignUp API can be used for creating a user, and login for returning token of that user. Only if malicious developer has credentials, then he can access tokens and auth APIs. There is also something about DDOS attacks so you can maybe write logic to temporarily block IPs where hits frequency is high.
You can also store device ID of signing user, which seems idle for your scenario. Entertain hits from that deviceID only. Similarly, user can add more devices with their credentials. I think even Google does that (generate alerts if user creds are signed in from new device and add the device to list if user confirms). Hope this helps.
I have a pre-existing iOS & Android app, that I'm making an update for that includes a RESTful services API and Facebook login for user authentication. The general flow of the app is:
Users "logs in" to my app, via Facebook's SDKs, which return an access token to my app.
App calls a RESTful service, including the Facebook access token as a parameter (using HTTPS and SSL)
Service that is called, sends the received access token (and app secret stored only on my servers) to Facebook to verify who the user is, and performs actions based on that. Facebook is set to require app secret from server-side calls.
My app has gained popularity and has several clones already, and I want to prevent these clones from being able to use my RESTful API (as I am sure that they will try to do when I release the update). Let's assume that the clones are smart, are using the same Facebook access tokens that my app does (if this is possible), and are following a similar pattern & frequency of calling the API that my app does.
Is there anyway to ensure, or nearly ensure, that calls to my services are coming only from my app, and not the clones?
Thanks in advance!
You can do this by including a signature in the request, and verifying it.
App Side:
do something like: signature = md5( md5(url + data) + MY_RANDOM_KEY)
append signature to the data, or url, etc.
send call to REST api (as usual)
Server Side:
extract the signature from the body/url (and remove it from there).
calculate what you think it should be: signature_should_be = md5( md5(url + data) + MY_RANDOM_KEY) [keep in mind you've removed signature from url/data so that you get url/data in its original pre-hash state]
verify that signature and signature_should_be are equal
Doing this, along with SSL, should make your API secure enough.
You could do as Tommy Crush suggests and add a secret inside you application. But if you are up against clever opponents, this probably won't help. The attackers can either decompile your application or try to simply reverse engineer your signature algorithm.
It is important to remember that anything stored within your application should be thought of as already compromised, as an attacker can decompile your app and scour through your code as much as he/she pleases and extract anything he/she wants from it. You cannot rely on anything in your application to be safe inside your app, since an attacker can extract it from your app into their app.
It is important to note that you are using trying to use OAuth for authentication, which is not intended for. It is simply meant for authorization, which is not the same as authentication. Authorization simply gives you access to a resource, but does not tell you who accessed it, which is the problem you are facing. To authenticate your users as your real users (or as close as you can get), you would need to add a login service for your service - something like rolling your own OAuth-server, or similar. Then you can decide who can access the resource, which in this case is your RESTful API :)
If this is more work than it is worth, then Tommy's scheme is a good alternative :)
The de facto solution for authentication on restful APIs like Twitter and Facebook use is the OAuth mechanism.
You can find more details here: http://en.wikipedia.org/wiki/OAuth.
OAuth is supported from the majority of the languages with external libraries.
On Android for example there is the https://github.com/wuman/android-oauth-client library.
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.