10
votes

I have been digging into Play2!Scala documentation about possible ways of implementing authentication/authorization for user requests and I must say that I am a little bit lost. I would like to know more about how requests sent from mobiles devices are authenticated/authorized on a Play2!Scala-backed REST-service.

First of all, it seems that there are many auth-modules for Play2/scala : e.g t2v's Play20-auth. But the thing is, these solutions are based on storing cookies on the client-side. Is that Right ? Which makes sense in a pure web perspective : requests are sent from a browser, the server can store cookies on the client etc.

Now, what if I have a native mobile application (on IOS or Android) and I am just calling a REST service backed by a Play2!Scala app. In this case, I am not using a browser, so the server can not store cookies on the client app.

Can I still use modules like t2v's Play20-auth for authorization/authentication ?

What are the best practices for dealing with this kind of thing ?

Any help would really be appreciated, Thanks in advance,

1
No, the Play auth module you're referring to can't be used for stateless REST authentication because yes, it uses cookies. I would suggest you look at similar questions such as stackoverflow.com/questions/454355/… it's not really all that hard to implement your own. I would suggest staying away from OAuth unless you're a masochist though.thatsmydoing

1 Answers

9
votes

Ok, this is for authentication, then the login is separate, you can use your own system or something like openID, etc. The problem is how to store that the user is authenticated.

The main idea for securing your REST service would be to use an auth token that is signed on the server side with some identifier of the user. It would go this way:

  1. the user enters a id/password
  2. a rest method checks this and if it's valid, sends a token back to the phone. You store that in your app
  3. every time you make a call to your rest API you send the user id and the token and you check the token on the server.

You have two solutions for generating and checking tokens:

  1. The token is basically the user id, concatenated with some salt of your own (whatever secret message you want) and then signed with a private key on your server. Personally I have done this with HMAC-SHA256 (using javax.crypto in my scala code). If someone tries to use your REST API, they won't be able to generate the token as they do not know your private key nor the secret. Every time you receive a request on your REST API (3), you just recompute the hash and compare it with the one you were sent as a token.
  2. Instead of a HMAC with the user ID, another solution is to store a random number in your database for each user. This will be your token. Every time you receive a request, you check in the database the secret token for that user and see if it's the same as the one from the query.

This will create infinite tokens, so your user will never be logged out, you can add an expiration date to these solutions quite easily:

  1. if using HMAC, you put in your token (before signing) the current date. For instance, if you want a 24h session, you can do something like:

    val format = new SimpleDateFormat("d/M/yyyy");  
    isoFormat.setTimeZone(TimeZone.getTimeZone("UTC"));  
    val date = format.format(new Date());  
    val token = calculateHMAC(userID + date + secret);  
    

    for shorter/longer periods, you change the format to include more or less so that every time you generate the token to check it you fall in the same period.

  2. for the random number/database solution, you just store the date of creation of the random token, and you see if it's in the period you like.

If you are using an OpenID (or similar) identification from a third party, you will have to show a WebView to the user where you load the openID provider's page, you just have to make sure that the redirect page after the authentication contains a generated token hidden somewhere (in the title for instance) and you extract it with your app code.

This is pretty straightforward to implement yourself, but I have seen a plugin for play2 to deal with token auth: https://github.com/orefalo/play2-authenticitytoken (never used personaly) and one for stateless auth: https://github.com/blendlabs/play20-stateless-auth

For the loggin bit, you don't have to implement that, there are good modules out there for play: