Search code examples
scalaplayframework-2.1deadbolt-2

Deadbolt 2 Restrict function has only one possible failure code


This question may have a bit of philosophical aspect to it.

I have been using Deadbolt 2 (Scala) in my Play application and it works quite well.

In looking at the Restrict function definition (line 47) I noticed that it will invoke the onAuthFailure for one of the following reasons:

  1. No user in session (no subject)
  2. Action specified no roles.
  3. User attempted an action for which they did not possess one or more required roles.

In my application UI, I would like to receive a different status code for each of these so that a user that is not logged in (condition 1) will be redirected to login page but condition 3 would be more gracefully handled by just a warning (since they can do no harm anyway and might have accidentally tried to edit when they have 'read-only' access - perhaps a UI bug, but logging in again is a bit draconian).

If I had to settle for just 2 status codes, however, I would want to differentiate between 1 and the other 2. I can see how this could be accomplished but would like to get other opinions on the merits of even doing this.

If I were to implement this change, it looks like I could just override the Restrict function in my own extension of the DeadboltActions trait.

I'm a little new to scala, so I'm open to additional ideas on how to best accomplish these goals.


Solution

  • I decided to just add the code to differentiate between condition 1 and either 2 or 3 as follows:

    In MyDeadboltHandler:

    class MyDeadboltHandler(dynamicResourceHandler: Option[DynamicResourceHandler] = None) extends DeadboltHandler {
    ...
      def onAuthFailure[A](request: Request[A]): Result = {
        Logger.error("authentication failure")
        val json = new JsonStatus("Failed to authenticate", -1).toJson.toString
        if(noUserInSession(request)){
          Results.Forbidden(json).withHeaders("Access-Control-Allow-Origin" -> "*")
        }
        else{
          Results.Unauthorized (json).withHeaders("Access-Control-Allow-Origin" -> "*")
        }
      }
    
      def noUserInSession(request:RequestHeader) = {
        username(request) match {
          case Some(u:String) => false
          case _ => true
        }
      }
    

    This works well for me and does not impose upon the basic Deadbolt-2 functionality.