I am having trouble grasping the idea of authorization in PlayFramework (version 2.5). My situation is I have a REST API method getUser
and I want to restrict its access by performing authorization with a token that is coming in custom request header named "X-Authorization"
. Now my controller code looks like that:
package controllers;
import models.User;
import org.bson.types.ObjectId;
import play.mvc.*;
import org.json.simple.*;
import views.html.*;
public class ApiController extends Controller {
public Result getUser(String userId) {
User user = User.findById(new ObjectId(userId));
JSONObject userG = new JSONObject();
//Some code to append data to userG before return
return ok(userG.toJSONString());
}
}
The route URL is defined like this:
GET /api/user/:id controllers.ApiController.getUser(id)
Option 1 could be to check the Authorization token inside the method getUser
and also check for other credentials but I want to restrict access before even it get calls getUser
method. As in future I will be adding more method calls to this REST API. So I will be reusing the same authorization to those future REST APIs as well.
I found there is authorization available in Play Framework which I am not able to understand. I tried to implement Authorization by extending class Security.Authenticator
and overriding methods getUserName
and onUnauthorized
like this:
package controllers;
import models.Site;
import models.User;
import org.json.simple.JSONObject;
import play.mvc.Http.Context;
import play.mvc.Result;
import play.mvc.Security;
public class Secured extends Security.Authenticator {
@Override
public String getUsername(Context ctx) {
String auth_key = ctx.request().getHeader("X-Authorization");
Site site = Site.fineByAccessKey(auth_key);
if (site != null && auth_key.equals(site.access_key)) {
return auth_key;
} else {
return null;
}
}
@Override
public Result onUnauthorized(Context ctx) {
JSONObject errorAuth = new JSONObject();
errorAuth.put("status", "error");
errorAuth.put("msg", "You are not authorized to access the API");
return unauthorized(errorAuth.toJSONString());
}
}
Then I've appended the annotation to the getUser
method with @Security.Authenticated(Secured.class)
. It works fine and returns unauthorized error. But now I am not sure if that is the preferred way. I feel this is not the right way to do it as the name of the override of function getUsername
suggests that too. I am not checking for any username in session or cookie rather only the token present in the header of request.
Also I know there is a module named Deadbolt
which is used for authorization but I read its documents and I am not able to integrate it. It was relatively complex integration for a beginner like me. I was confused about how to use it. I thought about using SubjectPresent
controller authorization but still I was not able to implement it successfully.
In the end what do you guys suggest that should I use Security.Authenticator
the way I have implemented? Or do you suggest that I go to my first option that is checking authorization inside getUser
method? Or Anyone can tell me how to implement Deadbolt
in my scenario?