I'm developing an Android application which consumes a public REST API, in which I have been provided with a developer key. How should I implement the key in my application ?
Will every application in different devices have my same developer key embedded into them? And if so, I only have a limited quota for the developer key, How should I manage it?
Or How to have different unique API keys for each app on different devices so that each application has their own quota and how should I manage it?
For example - Scenario 1(Question 1) - Suppose the Developer quota = 1000 hits, and application runs on 5 different devices then, on accessing and retrieving the info from the API would deplete my developer quota very fast.
Scenario 2(Question 2) - On not using the developer key(quota) , here each application on each devices have their individual quota = 1000 hits. Simply like each device having their own account.
I'm new to REST APIs and thought about the scenarios above but I don't know how to implement and manage them or what is the actual correct solution of Implementing a REST API key in my application?
I have already successfully tested my application on my device using my developer key.
For the quota management, it's the backend logic and it handles user requests so you should follow the backend way in scenario 1. Here is how it should work.
Device Login. On success, the server returns an access token as a response. Store token in device safe place(i.e. SharedPreferences in android).
Send the token in Authorization header of every request to the server, Your server should be guarded by Authorization. Server updates the quota consumed for the day. Here is how the server can manage quota,
‣ Identify user based on the token in Authorization header and update the quota.
‣ If quota exceeds, return some meaningful error to the device.
For scenario 2, make the token User Independent (multiple device logins allowed for the same account). By making the token User Independent and above given flow, you can achieve aspects given in your question. let me know if you have a question.
I suggest using JWT Token. as it's a standard JSON web token and globally used. it has several benefits and availability on major platforms.
You can implement the API key either in headers of the API or in the parameters.
For example if you are using Retrofit the implementing key in headers will look like this :
#Headers({"key: your_key"})
#POST("user/classes")
Call<playlist> addToUserlist(#Body UserParam parm);
Or if you want to implement it in parameters it will look like this :
#POST("user/{key}/classes")
Call<playlist> addToUserlist(#Path("key") String your_key);
Related
I'm developing an android app and I want to restrict access to my API to my website and mobile application. I'm not interested in having the user login into my app, rather, registering the client.
I've refrenced these resources for this task:
how to make google endpoints inaccessible from the web?
How do I protect my API that was built using Google Cloud Endpoints?
https://cloud.google.com/appengine/docs/java/endpoints/add-authorization-backend
How do I restrict Google App Engine Endpoints API access to only my Android applications?
Here is what I did thus far:
Generated an android and web client api key from the google cloud console. It looks something like this: ALzfShCF_mD_IVlVVVf2783TG9FG8x7u0s-ZFQE (not real key)
Made a constants class, added these to my API declaration for clientIds
clientId{android_key,web_key} && audience{web_key,android_audiance}
Added a User user param to each method
Rebuilt project, deployed.
All of these resources seemed helpful, especially the documentation. However, I didn't notice any difference. I expected to see, after I followed the documentation and redeploy my backend, both my website and app fail to call my endpoint functions. However, they both worked flawlessly.
Would following these posts or documentation prove my case, or is there something else I must do? I also dont want unauthorized access to my API explorer as well!
Any help would be greatly appreciated!
Edit:
I'm using the wrong keys, I was using the API key instead of the CLIENT Id. Once I updated that I saw that my API requests are failing because the user param is null. Now my question is, how can I not pass a non-null user object without getting the user to login?
I tried making a GoogleAccountCredintal and passing it to my ApiBuilder in my Async task, but its always null.
GoogleAccountCredential credential = GoogleAccountCredential.usingAudience(context,APIClientKeys.ANDROID_CLIENT_ID);
MyApi.Builder builder = new MyApi.Builder(AndroidHttp.newCompatibleTransport(),
new AndroidJsonFactory(), credential) ...
A very wise web developer once said
"Never Trust the Client".
No matter how sophisticated mechanism you come up with to secure your application, all it takes is a Network Inspector (Like one you can find in your web-browser) and a code inspector (which you can also find in your web-browser). Now some might suggest to obtrucify your client (that is mangling code enough that someone can not just see it). However, if someone really wants to de-obtrucify your application. With significant effort they will and once they have successfully reverse engineered your client, they can write their own malicious client to abuse your endpoints.
So what can you realistically do?
Rate limit usage on some endpoint using some rate-limiting technology (like Limitd) by an IP or other parameters and then start blacklisting IPs if they abuse your service this will make it really hard to abuse your apis.
Force users to login.
How about this:
Setup a secret key on your server and your app. Let’s say it’s SECRETKEY123. When making a request to your API, send an extra parameter called auth. In it pass the md5 (or any other, say bcrypt) hash of your parameters and the secret key. (Note: The secret key should not be posted)
So something like auth = md5(param1 + param2 + SECRETKEY123);
Then on your server perform the same hash using the secret key already stored on the server. Compare the two hashes – I.e the one you submitted and the one you generatd on the server. If they match allow access – otherwise restrict access.
Users sign up in my platform from the mobile app (Android & iOS). Once they have completed a form, I do a RESTful call to my server with the username and password and an API key.
https://api.example.com/v1/users/register
I assume that the API key is not protected since it is embedded in the app, so anyone can actually make that RESTful call and register as many users as they want.
How can I protect this call so that users can sign up ONLY from the mobile app? How do other apps (e.g. Facebook, Twitter,...) solve this problem?
How can I protect this call so that users can sign up ONLY from the
mobile app? How do other apps (e.g. Facebook, Twitter,...) solve this
problem?
There is no way to restrict your RESTful call just for mobile phones. Anybody could emulate that call impersonating a device manipulating headers or whatever. The only way to face this problem is to have a good security protocol design between your app and your backend.
As you mentioned, Facebook and other big companies do not store any API Key since the beginning in their app, instead they allow users to sign up through a website or mobile setting up specific user credentials. These signing ups are protected agains massive registration attacks using anti-bot techniques both from client (CAPTCHA) and server side (source IP + timings). Once those credentials are created and authenticated, their endpoint will return a client specific token which would be valid to make further REST API calls, and only this very user will be authorized to use that token for a limited period of time. One typical approach nowadays is to use Oauth 2.0 as you can see in many public API specifications like: Paypal, Twitter, Facebook, etc. I suggest to research other famous REST API specifications, you can learn a lot from them.
Almost all of known techniques mentioned before like CAPTCHA, server side checks and so on could be defeated by a hacker. However, if you still want to add some additional barriers to avoid unlimited user accounts, one good idea can be to add two-step verification process to verify an account. Unless this process is finished correctly, the user won't be able to use your backend API (apart from the one to authorize the account). Thus, a user may be able to create a few accounts with different phone numbers, but never an unlimited amount of them.
I think you have to devise a flow like reCAPTCHA. Its documentation may give you a hint.
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.
Let's say I have this application developed for Android which needs to use a Facebook (or Twitter or Google or all of them) based authentication so it can access this private API I've developed with nodejs' Express for example (could be any other platform too). I've read this answer here that gave me a hint on how to associate my authentication model with my user model (and another one here that made me realize those two parts are different), Facebook authenticates and I use some information they provide to create an "identity" for this user, but what exactly is this information that will create a link between the user and the identity? no abstract terms please, do I need to use and send either the access token or the Facebook user id? or would I just send the access token and let the server get the user id?
Regarding new requests after this user has been authenticated, I've read about API keys of some sort, which are basically some random strings that I should add to my identities (or users? this part confuses me) entities, and they should be securely stored in the mobile device as a mechanism to authenticate further requests, but how do I securely get this random string to the device in the first place? am I misunderstanding the way API keys work? are Facebook authentication and API keys mutually exclusive? if so, what would I use for further requests just using a provider for my authentication? it seems illogical to pass the access code in every request, even more so passing the user id.
The focus of this question is for me model a solid strategy for managing this authentication-user-identity behavior, would love any insights on how has this been done before since the material I've found in SO and the web has been very lacking, often referring just to server side implementations or just authentication answers, not addressing the issue of further requests.
The Facebook/User ID is there to identify the (returning) User. Keep in mind that you only get an "App Scoped ID", not the "real" ID - it will be unique in the App, but different in another one. See changelog: https://developers.facebook.com/docs/apps/changelog
Access Tokens are there to make calls to the Graph API. There are 3 different Tokens (App Token, User Token, Page Token), you can read more about them in those articles:
https://developers.facebook.com/docs/facebook-login/access-tokens/
http://www.devils-heaven.com/facebook-access-tokens/
You can store Access Tokens for later, but in most cases you don´t need to store them - only if you need to access the API while the User is not using your App.
In general, App Tokens can be used to request public stuff and to change App settings. User Tokens can be used to request (or post) User stuff and Page Tokens can be used to request insights of a Facebook Page and other things.
If you want to deal with Access Tokens on your own, make sure to activate appsecret_proof in the settings. I suggest reading this article about securing API calls: https://developers.facebook.com/docs/graph-api/securing-requests
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.