I have an app that retrieves data via http from a server. App sends a POST request with some variables to execute the query and retrieve the data in a JSON format.
The problem is I don't find a way to make the data secure into my server (only accessible to users that have MY application installed). If someone gets my app, and decompile it (even ProGuard won't avoid this for too long) a modded app could start sending requests to my server, using exactly the same protocols, parameters and IP address.
So, in a nutshell, the question is: Is there a way to check (server side, of course) if a request is coming from a legit user?, any way to check if the requester is using my app and not a modded one?
PS: I've been looking for questions like this one and only found another close one that suggested a "user login" approach as answer. I don't want to bother my users with any login mechanics.
Thanks in advance.
Google offers a method to verify back-end calls from an Android app as part of Google Play Services which allows you to verify that the back-end call came from your signed application. One advantage that it has is there is no user login required to verify calls due to the client ID scope used to get the auth token.
Related
My mobile app does some API calls during usage and some of them should not be possible from anywhere else (e.g. postman)
For instance if you have a database table user and a column membership and the app-user does an in-app-purchase an API call is made to update that row and change the column from e.g. standard to premium
Now in theory if someone knows the URL and sends an HTTPS request he could upgrade himself without purchasing anything. I am researching for a while now but feel a bit lost. There is no registration or login. I use the unique hardware ID of the users devices as a primary key to store everything in the database. I thought about something like:
When the user opens the app a request is send and the server responds with a randomly generated key
All requests the user makes have to use that key which I would send in the header otherwise it gets rejected
Is this the only thing I can do? What is the best practice for a mobile app that does not use any kind of registration?
If it matters I used flutter for the app and flask for the backend that is connected with a postgres database
edit: I am using HTTPS everywhere not HTTP
If the api is open as you have described in the architecture then there is no way this can be achieved without having a login mechanism like OAuth or one of those provided by Google Login or Facebook Login. You will have to provide a way for client device to tell you who are you talking with.
Else you can hide this api behind a closed network so that only server can call this api which will only do so after a successful response from the payment gateway. That way you can enable the hit to come only from the specific server ip address.
Also the fact that you want HTTP instead of HTTPS makes this very vulnerable to a number of attacks.
I want to develop an Android application in which anonymous users can send requests to my server through HTTPS. I need to make sure that the requests are coming from my app since anyone can craft an HTPP request and send it. This is very critical in my app.
I read about GCM tokens, but I don't know if they can help me in my issue.
Is there a way to authenticate the requests (coming from the app) without hiding secret keys in code (because I read that hiding secrets is a bad practice as de-compilation is very trivial in Android).
Thanks
You can always generate a unique token for your user. And add that token in the header of your request and verify it on your backend.
Your server could generate unique PIN for each user of your app and it is then sent to your app and displayed over the app.
Users, even though anonymous, are supposed to enter the same PIN before sending the response. In turn request could carry this PIN that server can verify that indeed it has come from the same app.
Further you can set timeout for validity of each PIN is valid so that it is not mis-used and always latest PIN generated are used at the end of any session.
One question further to be answered related to point 1: Is how to ensure that this PIN is sent to your app and not to any fake app.
Answer to that will be : For this every app will get unique applicationid when installed on android device. While installation, this applicationid could register with your server in a discreet manner. So this way you ensure that all your API calls are coming from registered app.
I figured out how to solve this issue after following this guide: https://android-developers.googleblog.com/2013/01/verifying-back-end-calls-from-android.html
Basically, You use the GoogleAuthUtil class, available through Google Play services, to retrieve a string called an “ID Token”. You send the token to your back end and your back end can use it to quickly and cheaply verify which app sent it and who was using the app.
When your server receives the token from your Android app, it’s really important that you verify it. This requires two steps:
Verify that it’s really signed by Google.
Verify that it’s really meant for you.
Thanks.
I have a background in web development but I am very new to the mobile world. So, I'm not sure how to proceed with this situation:
The user login in the app
The credentials are sent to the server through a POST request.
If the response is ok, it redirects to the main activity.
Now, I want to know if I have to keep the user's ID or not. I know that when we are using a browser the server saves a "session" so the client doesn't need to send the ID everytime to request data. Is that also true with mobile apps (Android)?
By the way, I'm also responsible for building the REST API but don't have any experience targeting mobile devices.
Big question to answer, and it depends and not sure what server technology you are using. However I can describe an approach I implemented (.Net background).
It seems you are writing a mobile app?
The mobile app would first make an authentication call passing id and password to your login api, over https of course. Often the url would be something like
//yourwebsite/Account/Token
Your api would validate the user and if ok, issue a bearer token.
The mobile app needs to remember this token and on subsequent calls pass this in the request header. That's how the server will know who this is. You don't need to send the user id and password any more. And there may be a strong security argument for not storing the user id and password on the mobile device at all.
Now, your server code will validate the token, and you will know who and what the user can do. The token typically expires, so any mobile client needs to check for this and re-authenticate to get a fresh token.
But how will the server know this token, who it belongs to?
In an MVC world for example, there's framework code to help here. There's plenty of MVC template code. If you happen to be developing .Net api services, see this http://www.asp.net/web-api/overview/security/individual-accounts-in-web-api
If you are not .Net on the server, I'm sure there will be something else to help you along the same principals.
As for developing RESTful API's, ServiceStack is seriously worth considering. If too expensive, at least consider their approach and roll your own (especially when it comes to versioning of your api's).
You misunderstand the case with browsers, therefore your conclusion is flawed. Let me explain: When you log in to a website using a web-browser, a session is saved indeed, but not only on the server. It is saved at the client-side as well. Whenever you send a request from there on to the server, you have to send that stored information as well, called cookie to identify yourself.
Let's think about this more deeply: How would a server identify your session as being your session without getting a cookie? By IP address? Nope, the IP address can be used by many and it might change. By browser session? Yes, by browser session, which includes the cookie as well.
Now that you understand that the session is saved by both the server and the client, you surely already know that you need the very same for mobile apps as well. The client logs in, therefore a cookie is generated for the client. This should be difficult to guess. From there on, the client uses the server using the cookie created for it.
If you do not believe me, visit a website where you are not logged in, and then run console.log(document.cookie);, log in, then run console.log(document.cookie) again, then log out andd run console.log(document.cookie) again.
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'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.