Silhouette

Authorization

Silhouette provides a way to add authorization logic to your secured endpoints. This is done by implementing an Authorization object that is passed to all SecuredRequestHandler and SecuredAction as a parameter.

After checking if a user is authenticated the Authorization instance is used to verify whether the execution should be allowed or not.

/**
 * A trait to define Authorization objects that let you hook
 * an authorization implementation in secured endpoints.
 *
 * @tparam I The type of the identity.
 * @tparam A The type of the authenticator.
 */
trait Authorization[I <: Identity, A <: Authenticator] {

  /**
   * Checks whether the user is authorized to execute an endpoint or not.
   *
   * @param identity The current identity instance.
   * @param authenticator The current authenticator instance.
   * @param request The current request.
   * @tparam B The type of the request body.
   * @return True if the user is authorized, false otherwise.
   */
  def isAuthorized[B](identity: I, authenticator: A)(
    implicit request: Request[B]): Future[Boolean]
}

Below is a sample implementation that only grants access to users that logged in using a given provider. This example comes in two variants. The first has a defined authenticator type which is only applicable to actions which are defined with the same authenticator type. The second example uses a generic authenticator type which is applicable to any kind of action, regardless of the authenticator type defined for this action. The second case can also be used with a generic identity and it's useful if the authorization depends either on the identity or the authenticator.

case class WithProvider(provider: String) extends Authorization[User, CookieAuthenticator] {
  
  def isAuthorized[B](user: User, authenticator: CookieAuthenticator)(
    implicit request: Request[B]) = {
    
    Future.successful(user.loginInfo.providerID == provider)
  }
}
case class WithProvider[A <: Authenticator](provider: String) extends Authorization[User, A] {
  
  def isAuthorized[B](user: User, authenticator: A)(
    implicit request: Request[B]) = {
    
    Future.successful(user.loginInfo.providerID == provider)
  }
}

Here’s how you would use it:

class Application(silhouette: Silhouette[DefaultEnv]) extends Controller {

  def myAction = silhouette.SecuredAction(WithProvider("twitter")) { implicit request =>
    // do something here
  }
}  
class Application(silhouette: Silhouette[DefaultEnv]) extends Controller {

  def myAction = silhouette.SecuredAction(WithProvider[DefaultEnv#A]("twitter")) { implicit request =>
    // do something here
  }
}  

Info

Errors for not authorized users can be caught with the global or local error handlers.

Logic Operator

You can use the logical !, && and || operators to create logical expressions with your Authorization instances. You also need to have an implicit ExecutionContext in scope.

def myAction = silhouette.SecuredAction(!WithProvider("twitter")) { implicit request =>
  // do something here
}
def myAction = silhouette.SecuredAction(WithProvider("twitter") && WithProvider("facebook")) { 
  implicit request => // do something here
}
def myAction = silhouette.SecuredAction(WithProvider("twitter") || WithProvider("facebook")) { 
  implicit request => // do something here
}

Updated about 15 hours ago


What's Next

Identity

Authorization


Suggested Edits are limited on API Reference Pages

You can only suggest edits to Markdown body content, but not to the API spec.