Skip to content
Manabu Nakamura edited this page May 11, 2013 · 7 revisions
  1. First create a trait that extends jp.t2v.lab.play2.auth.AuthConfig in app/controllers.

    // Example
    trait AuthConfigImpl extends AuthConfig {
    
      /**
       * A type that is used to identify a user.
       * `String`, `Int`, `Long` and so on.
       */
      type Id = String
    
      /**
       * A type that represents a user in your application.
       * `User`, `Account` and so on.
       */
      type User = Account
    
      /**
       * A type that is defined by every action for authorization.
       * This sample uses the following trait:
       *
       * sealed trait Permission
       * case object Administrator extends Permission
       * case object NormalUser extends Permission
       */
      type Authority = Permission
    
      /**
       * A `ClassManifest` is used to retrieve an id from the Cache API.
       * Use something like this:
       */
      val idTag: ClassTag[Id] = classTag[Id]
    
      /**
       * The session timeout in seconds
       */
      val sessionTimeoutInSeconds: Int = 3600
    
      /**
       * A function that returns a `User` object from an `Id`.
       * You can alter the procedure to suit your application.
       */
      def resolveUser(id: Id): Option[User] = Account.findById(id)
    
      /**
       * Where to redirect the user after a successful login.
       */
      def loginSucceeded(request: RequestHeader): Result = Redirect(routes.Message.main)
    
      /**
       * Where to redirect the user after logging out
       */
      def logoutSucceeded(request: RequestHeader): Result = Redirect(routes.Application.login)
    
      /**
       * If the user is not logged in and tries to access a protected resource then redirct them as follows:
       */
      def authenticationFailed(request: RequestHeader): Result = Redirect(routes.Application.login)
    
      /**
       * If authorization failed (usually incorrect password) redirect the user as follows:
       */
      def authorizationFailed(request: RequestHeader): Result = Forbidden("no permission")
    
      /**
       * A function that determines what `Authority` a user has.
       * You should alter this procedure to suit your application.
       */
      def authorize(user: User, authority: Authority): Boolean =
        (user.permission, authority) match {
          case (Administrator, _) => true
          case (NormalUser, NormalUser) => true
          case _ => false
        }
    
      /**
       * Whether use the secure option or not use it in the cookie.
       * However default is false, I strongly recommend using true in a production.
       */
      override lazy val cookieSecureOption: Boolean = play.api.Play.current.configuration.getBoolean("auth.cookie.secure").getOrElse(true)
    
    }
  2. Next create a Controller that defines both login and logout actions. This Controller mixes in the jp.t2v.lab.play2.auth.LoginLogout trait and the trait that you created in first step.

    object Application extends Controller with LoginLogout with AuthConfigImpl {
    
      /** Your application's login form.  Alter it to fit your application */
      val loginForm = Form {
        mapping("email" -> email, "password" -> text)(Account.authenticate)(_.map(u => (u.email, "")))
          .verifying("Invalid email or password", result => result.isDefined)
      }
    
      /** Alter the login page action to suit your application. */
      def login = Action { implicit request =>
        Ok(html.login(loginForm))
      }
    
      /**
       * Return the `gotoLogoutSucceeded` method's result in the logout action.
       *
       * Since the `gotoLogoutSucceeded` returns `Result`,
       * If you import `jp.t2v.lab.play2.auth._`, you can add a procedure like the following.
       *
       *   gotoLogoutSucceeded.flashing(
       *     "success" -> "You've been logged out"
       *   )
       */
      def logout = Action { implicit request =>
        // do something...
        gotoLogoutSucceeded
      }
    
      /**
       * Return the `gotoLoginSucceeded` method's result in the login action.
       *
       * Since the `gotoLoginSucceeded` returns `Result`,
       * If you import `jp.t2v.lab.play2.auth._`, you can add a procedure like the `gotoLogoutSucceeded`.
       */
      def authenticate = Action { implicit request =>
        loginForm.bindFromRequest.fold(
          formWithErrors => BadRequest(html.login(formWithErrors)),
          user => gotoLoginSucceeded(user.get.id)
        )
      }
    
    }
  3. Lastly, mix jp.t2v.lab.play2.auth.AuthElement trait and the trait that was created in the first step into your Controllers:

    object Message extends Controller with AuthElement with AuthConfigImpl {
    
      // The `StackAction` method
      //    takes `(AuthorityKey, Authority)` as the first argument and
      //    a function signature `RequestWithAttributes[AnyContent] => Result` as the second argument and
      //    returns an `Action`
    
      // thw `loggedIn` method
      //     returns current logged in user
    
      def main = StackAction(AuthorityKey -> NormalUser) { implicit request =>
        val user = loggedIn
        val title = "message main"
        Ok(html.message.main(title))
      }
    
      def list = StackAction(AuthorityKey -> NormalUser) { implicit request =>
        val user = loggedIn
        val title = "all messages"
        Ok(html.message.list(title))
      }
    
      def detail(id: Int) = StackAction(AuthorityKey -> NormalUser) { implicit request =>
        val user = loggedIn
        val title = "messages detail "
        Ok(html.message.detail(title + id))
      }
    
      // Only Administrator can execute this action.
      def write = StackAction(AuthorityKey -> Administrator) { implicit request =>
        val user = loggedIn
        val title = "write message"
        Ok(html.message.write(title))
      }
    
    }