Saturday, November 1, 2014

Web Service Security and Native Mobile App User Authentication

In this article I am going to throw some light around web service security,  user Authentication  for native mobile applications and how both the topics are connected. Me along with my cool team members at Zycus were working on the same off lately. The idea is to highlight the fact that it is ideal to implement web service security by being agnostic to the type of web service clients (like mobile apps) but these decisions may impact the mobile app user authentication process.

If you are working on a mobile application that requires user authentication and fetching data from a server side application then it is highly likely that you are exposing certain functionality of your server side application via web services that can be accessed over the web by your mobile application.

While developing such applications you will usually encounter following challenges.
  1.  How to secure the web service endpoints?
  2.  How to authenticate users from the mobile app in secure way?
  3.  How to ensure that mobile app does not bundle or store any sensitive information which can result into illegal access to server side data by compromising access to web services.
How to secure the web service endpoints?

If I have to forget about the Mobile Application for a second and just answer this question from web services security perspective, then I would answer it in following way. Discussing each security method in detail is out of the scope of this article hence I have provided hyperlinks to references that I used while taking such decisions..

Public-ally hosted Web Services, if not properly secured, are mostly vulnerable to Man in the Middle, DoS, and Replay Attacks.

As data passing over HTTP is not encrypted and can be sniffed and modified by someone in middle, plain HTTP based web services are vulnerable to Man in the Middle attacks. To tackle this, you need to make sure that web services are exposed only over HTTPS and they are not accessible via HTTP.

To harden the endpoints further you can choose to implement Mutual SSL Authentication. Mutual SSL Authentication ensures that the web service client knows that server is trusted and the server knows that the client is trusted by verifying each others certificates during the SSL Handshake.

Tackling DoS or Distributed DoS is not that easy as well. If you are using a web server like Apache then you can enable Mod_Security and Mod_Evasive rules to deal with DoS and DDoS or implement your IT infrastructure monitoring using Nagios.

Simplest way to tackle Replay attacks is by asking for a timestamp and a cryptographic nonce value as part of the HTTP request header. For simplicity timestamp can be enforced to be passed in UTC timezone. Server can verify the timestamp and check whether the request was initiated by the client not before a threshold value of say 5 minutes. Server can also verify a given nonce value and store it for certain amount of time so that any given request with same nonce should not be served again and should be discarded by the server.


How to authenticate users from the mobile app in secure way?

There are multiple solutions available and documented on the web. Each of them are best in their own way. I have seen many applications use the following approaches.
  1. OAuth2: Authorization Code Flow
  2. OAuth2: The Resource Owner Password Flow 
  3. Custom Implementation
OAuth2: Authorization Code Flow  

This could be one of the best ways out there but I am not so much in favor of using this approach. The reason is simple, it requires your app to do the OAuth Dance. Which will require opening up an embedded browser like WebView or UIWebView and take the user to the actual web application where the user can key in the credentials and is returned back with an access token once he authorizes the mobile application on his behalf to access the resource via web service calls. Mobile App can use the access token till the time it expires and carry on with accessing the user's data on behalf of the user. This model fits in well when the Mobile Application is using services provided by a third party web application., like you creating your own mobile Twitter App. In that case the end user using your version of Twitter App should authorize your App by indicating Twitter to allow your App to access resources on user's behalf.

If you our your company are the owners of both the web application and the official mobile application then this approach does not fit well.

OAuth2: The Resource Owner Password Flow 

This approach fits in well in a scenario where you or your company are the owner of the web application (or the API's exposed) and you or your company is planning to implement an official Mobile App for the corresponding web based application.

Actually OAuth was primarily created for a different purpose. Let me point out that "OAuth provides client applications a 'secure delegated access' to server resources on behalf of a resource owner". Hence it is not a way to secure your web services but rather a way to authorize 3rd party web service clients like
  1. a mobile app developed by someone else (not by you or your company)  but using your web services
  2. or a 3rd party developed Web 2.0 widget embedded in a 3rd party web application accessing resource provided by your application.
  3. or a 3rd party web application accessing resources provided by your application
The Resource Owner Password Flow  of OAuth was just specifically created to provide a solution to handle this scenario.

It is advisable to go with this approach if you have enough time to implement an OAuth Provider which adheres to the specification.

Custom Implementations
I was actually searching on internet for quite some time to find out an easily understandable and well documented open source library which could help us implement an OAuth Provider which adheres to resource manager password flow specification. Although there are many libraries out there but either proper documentation was lacking or it was getting a bit difficult to understand.


I found a very good resource here which mentions about doing a custom implementation some what similar to OAuth resource manager password flow specification and it helped me to get started.

All right, so here I am going to explain the approach that we decided to go with.

So first of all, lets break down the problem statement into smaller problems.

We need to take care of following things
1) Secure the Web Services from Man in the Middle, Replay attacks and DoS attacks
2) Provide a secure way to authenticate users for my mobile app

Securing the Web Services from Man in the Middle attacks, Replay attacks and DoS attacks

To prevent man in middle attacks we decided to expose the RESTful web services over HTTPS so that the data transferred is encrypted.

However we wanted to harden the  web service endpoints further. The option we had was to use Mutual SSL Authentication. But wait, Mutual SSL Authentication requires Client Certificates (including the private keys) to be shipped along with the web service clients like mobile app.

Here is the mantra "any private keys you store in your mobile app is accessible to an attacker. " Each web service client (like a mobile app) should have it's own certificate and key pair, to prevent security being compromised.

Your server should also enforce protections, ensuring a compromised client can't just request anything. I am sure that there will be mobile applications which stores private keys and the corresponding server invalidates the compromised keys.

We didn't wanted to get into the certificate distribution problem and then decided to go with the digital signature verification. So here is how the digital signature verification works.

Tackling Man in the Middle attacks
  1. The client sends a request to the server over HTTPS
  2. In the request a custom HTTP header is passed with header name as x-signature
  3. The x-signature header value is a message digest of a concatenated string prepared by concatenating the request URL+HTTP Method+alphabetically sorted request headers and their values in lower case+Data within the message body
  4. We used HMAC SHA1 algorithm to create this message digest
  5. Once the request is received by the server the server generates another HMAC SHA1 signature based on message digest of the concatenated string prepared by concatenating the request URL+HTTP Method+alphabetically sorted request headers  and their values in lower case+Data within the message body
  6. Server then verifies the generated signature with the one passed by the web service client
  7. If both the signatures are equal then it means that request was not modified by anyone in the middle.
Tackling Replay Attacks
  1.  We introduced 2 additional headers custom headers x-nonce and x-timestamp which are to be passed by any web service client
  2.  x-nonce request header needs to have unique value generated by the web service client preferably a  secure random, server would then store this secure random for a limited time for a month or so and choose not to serve any other request having the same nonce value.
  3. x-timestamp request header contains value of a UTC time stamp of the time when the web service client initiated the request. The server cross checks passed time stamp with the server time and determines whether the request was not initiated by the web service client prior to a threshold value of 5 minutes. If the request was initiated prior to 5 minutes from the current server time then server would discard the request.
  4. Server can optionally choose to block those IP's from which replay requests are detected.
Tackling the DoS Attacks
Our web servers were fronted by Apache web server and we already had the Mod_Security and Mod_Evasive rules implemented along with infrastructure monitoring using Nagios in place. Hence we were not much worried about this.

So by this point we had a straight forward web application acting as an REST API Resource server with services secured using the above mentioned approaches. However we were left with mobile user authentication.

Mobile User Authentication

First of all we decided to maintain a registry of the web service clients who are authorized to consume the web services. If customers of our product are willing to consume our REST API's then they are required to register their web service clients with us which is possible only if they are licensed to use our products. On completion of registration form an application id is issued to user which can be used as part of the authentication process.

We decided to setup a new web application which will act as a REST API Authentication Server for authenticating the users willing to consume the REST API Resources from the Resource Server.

We decided to implement the authentication process in such a way that the consumer of the REST Resources from the Resource Server is supposed to obtain an access token from the Authentication Server prior to accessing any resources from the resource server. This access token should be passed in the x-access_token request header while issuing any calls to the Resource server. The validity of  access token issued by the Authentication server is for next 8 hours, which on expiry should be obtained again by going through the authentication process again. Here is how the user authentication was implemented.

  1. The web service client needs to pass the Application id (issued after application registration) in the x-application_id header with user id in the x-userId header along with x-signature, x-nonce and x-timestamp headers.
  2.  Auth Server validates the Application id and the User id with the user management module of our application. It checks whether the user is active and it exists in our database at this point. If the user exists and is active then a challenge is generated by the Auth Server and the value of this challenge is sent back as part of the x-challenge response header. The challenge generation process is mentioned below.
    1. First of all generate a secure random  (which will be the answer of our challenge).
    2. The generated secure random should then be AES Encrypted using the user's password as a key
    3. The encrypted value of the secure random is our challenge which the client needs to decrypt using the user's password and send back for verification.
  3. Client receives the challenge as part of the x-challenge response header and is supposed to AES decrypt it using the user's password.
  4. After decrypting it the client is supposed to issue another request to Auth Server with x-challenge_answer that contains the challenge answer (the actual secure random value) along with x-application_id, x-signature, x-nonce and x-timestamp.
  5. The server then verifies whether the answer of that challenge matches with the original secure random value or not. If yes then an access token is returned as part of the x-access_token response header.
  6. After receiving the x-access_token response header the web service client can use the token value along with x-signature, x-nonce, x-timestamp and x-application_id to access the resources for next 8 hours.
  7. On expiry of the access token the web service client is required to issue another call to Auth server

Hence the Mobile App User Authentication would look as depicted in the diagram below.




Also it is good Implement Certificate Pinning in your mobile application that accesses the web services.  This ensures that your mobile app trusts only the server that it is supposed to connect to by using the hard coded server certificate and ignoring the device's default trust store.

Hope this article would help others trying to do similar kind of implementation. Your comments and suggestions are welcome.

Update:
Recently I delivered a webinar on Building Secure RESTful WebServices on Techgig. The Webinar recording can be found here. It also has link to code samples of the custom implementation of securing web services described above.