Mobile application are becoming more popular than websites due to the ease of use and personalization they offer. As an application developer I have been working on Android application from last few month. As we get into mobile application development we will come across situation where we have to interact with a webservice to exchange information.
A typical example will be login, where user input his username and password which are verified with database hosted on a server over the internet. So it becomes very critical that the communication between mobile application and the server (webservice) is secure. When I say secure I mean:
- Mobile device can securely connect to webservice or server
- Server (webservice) can identify the connection and application calling it
- Server can verify if the request is legitimate and is not tempered during its journey over internet.
- Server can identify that the request is not a repeat request (Replay Attack) copied by a middle man to get response
So I have done some research online to check how most of the people are handling these points. Criteria was the solution should be simple,secure and easy to implement. In my case I was focusing on REST APIs but the solution can be used for any web based API following HTTP protocol.
I will explain all the above points one by one.
1.Mobile device can securely connect to webservice or server
To achieve this make sure your webserver is using HTTPS. This will ensure the connection between mobile application and webserver is encoded. So if any middle man is sniffing data between the application and server, he will not be able to get the raw content. The data over a HTTPS connection is encoded and can only be decoded by the webserver. More details here.
2. Server (webservice) can identify the connection and application calling it
This is one of the most important point. As webservice sits open on internet accepting all the connections coming to it, so, there has to be a mechanism for the webservice to identify if the call is coming from a legitimate application. To ensure this we have to maintain application IDs and secrect keys for our applications.
So for our mobile application we will create an “API Key” and “API Secret”. Both these values will be embedded in our application. API_KEY will be sent along with every request to server (webservices) so that server can match the API_KEY and process the request. Whereas API_SECRET will never be sent in request. Use of API_SECRET is explained in next step.
3. Server can verify if the request is legitimate and is not tempered during its journey over internet
A request when initiated by application will travel through ISP (internet service provider) and many routers to finally reach to our server. So a hacker can interrupt your request and change its content to access information which he is not authorised to. We need to ensure that server can identify a tempered request and rejects it. To achieve this we have to pass a security token in our request. A security token is created by using content of the request and API_SECRET.
Following is the list of steps to be followed for creating security token:
- Convert all the parameters into lower-case
- Arrange parameters in alphabetic order
- Add unix time stamp for additional security
- Generate hash (security token) using API_SECRET
Now with every request from mobile application we will send all the parameters, API_KEY, security token and unix time stamp. Unix time stamp will help us in the next step.
4. Server can identify that the request is not a repeat request(Replay attack) copied by a middle man to get response
After all this protection there still remain one case where a hacker can save your entire request and use it again to get the information called Replay Attack. To handle this we have added Unix Time Stamp in our request. By using Unix Time Stamp I don’t have to worry about the different time zones of my server and mobile application. Now to make this work we will assume a genuine time which a request might take to reach our server, in my case I assumed 5 seconds. So below is the list of steps which server will follow to verify if a request is “Replay Attack” or not :
- Get API_KEY from request and check if it exists in database ( generally we will cache it on server to save DB call on every request). If not then reject request or else go to next step.
- Get Unix Time Stamp from request. Generate Unix Time Stamp on server and calculate time difference. If difference is more than 5 seconds then reject the request. It is a Replay Attack.
Finally after all these measures, following is the list of steps server will perform before processing a request.
- Get API_KEY from request and check if it exists in database ( generally we will cache it on server to save DB call on every request). If not then reject request or else go to next step.
- Get Unix Time Stamp from request. Generate Unix Time Stamp on server and calculate time difference. If difference is more than 5 seconds then reject the request. It is a Replay Attack. If not go to next step.
- Convert all the parameters into lower-case
- Arrange parameters in alphabetic order
- As per the API_KEY fetch SECRET_KEY from database.
- Combine parameters , API_KEY and Unix Time Stamp to generate hash (Security token) using SECURITY_KEY(code shared on how to do it)
- Now compare this generated hash with the security token received in the request.
- If both the tokens match then process the request or else reject it.
Code classes to perform these steps in Mobile application (JAVA) and server side (PHP) are added on my github.
you can check the code here.
I have added example code with both the classes for Android as well as PHP.
16 Responses to “Writing secure REST webservices with PHP for Android”
July 24, 2015
business developmentWill share this post on facebook when I get home. On my iPhone at the moment. Great post.
July 27, 2015
imadHello Raj,
a great post and thank you. I need to know while connecting a barcode to a database made in mysql but the database is connected through the changes on a website, are there any more different steps for such an activity?
July 28, 2015
Rajinder DeolHi Imad,
I did not understand you question. Can you please specify what type of application you are talking about like website or mobile application and what are you trying to achieve.
July 28, 2015
imadhi,
so i need to display the different data of many products when i scan the barcode in a mobile app for android. I am confused as to how am i going to store or call the data from database which is in mysql whenever i scan any barcode of any product.
August 20, 2015
developer mobileIt’s a shame you don’t have a donate button! I’d certainly donate to this excellent blog!
I guess for now i’ll settle for bookmarking and adding your RSS feed to my Google
account. I look forward to brand new updates and will
talk about this site with my Facebook group.
Talk soon!
May 23, 2016
fix my computerHave you ever considered about adding a little
bit more than just your articles? I mean, what you say is important and all.
Nevertheless think of if you added some great graphics or video clips to give your posts more, “pop”!
Your content is excellent but with images and videos,
this site could certainly be one of the best in its field.
Excellent blog!
January 24, 2017
NaveenHeader in getHeader method is deprecated, Is there any alternative?
January 27, 2017
Rajinder DeolHi Naveen,
thanks for pointing this out, yes getHeader is depreciated since API version 22.
You can use jaja.net.URL.openConnection() for this.
I will update the code on github soon
March 15, 2017
bhaskHi Ray, thanks for writing this good post
im a beginner in android programming.
can you explain what should we add on parameter api_key and api_secret
I dont understand what Your-API-KEY and Your-API-Secret is
sorry if my question very basic 🙂
thanks in advance!
March 15, 2017
Rajinder DeolHi Bhask,
It is always better to ask, Your-API-KEY and Your-API-Secret will be replaced with API key and API secret. Think of them as your username and password which you will decide and use in your app.
For example API-key can be “my_awesome_app” and API-secret can be “PulSCqMnXGchW0”. The point to focus here is you will decide these two as per your choice.
June 13, 2017
MesaHi Ray, Thanks for your awesome article ^_^
could you please answer me, what should i put in ‘HEADER_ENCODED_HASH’ , ‘HEADER_TIME_STAMP’, static values or what?
thanks in advance ..
June 15, 2017
Rajinder DeolHi Mesa,
Glad that you liked the article, HEADER_ENCODED_HASH and HEADER_TIME_STAMP are constants to hold the name of these headers. When you make a http call you can send headers along with it.
When you encode you request in your Android app you will add these headers. So the name of headers you decided to put the encoded hash and timestamp should be the value of these constants.
August 9, 2017
HrishikeshWhere to store the Api_Key and API_SECRET. If someone decompiles the apk then he will get the api_key and api_secret
August 10, 2017
Rajinder DeolHi Hrishikesh,
Anything stored on client (android app) can be reverse engineered. You can certainly make the process more hard and time consuming by using different ways. There is a good article hiding-secrets-in-android-apps which discuss this in detail.
However there are still few ways to achieve a degree of security if the backend server you are accessing is in your control there is a good article discussing this approach how-to-hide-your-api-key-in-android.
November 7, 2018
PetarHello Raj,
Your post really helped me out to understand REST webservices. Anyway, I had issue with hashes. It gives me an INVALID_REQUEST error as they are different (from android and php). What do you think might be the problem? Thank you!
November 7, 2018
Rajinder DeolHi Petar,
I am glad my post helped you, can you please share some more details. Are you using the code I shared in github https://github.com/rajdeol/secure-webservices-php-android
If possible can you push your code to github and share the link.