t2v / play2-auth

Play2.x Authentication and Authorization module

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Can't mix AuthElement and OptionalAuthElement

takiri opened this issue · comments

Hi,

I'd like to extend both AuthElement and OptionalAuthElement in a same trait but I can't since methods 'proceed' and 'restore' are defined in the two of them, leading to ambiguity.

Thanks

Hi,

mmm, It's a bit difficult...
Can you use AuthActionBuulders instead of AuthElement and OptionalAuthElement ?

example) https://github.com/t2v/play2-auth/blob/master/sample/app/controllers/builder/Messages.scala
doc in japanese) https://github.com/t2v/play2-auth/blob/master/README.ja.md#actionfunction-としての利用

regards

Seems to be a less straightforward solution for us.

Here is our current workaround:

// Define a trait that can be used to define controllers with Auth capabilities
trait PWXAuthController extends PWXStackableController with PWXAuthConfig with AuthElement {
  val authorityKey = AuthorityKey
}
trait PWXLoginLogoutController extends PWXStackableController with PWXAuthConfig with LoginLogout {
  
  // BEGIN OF FORK OF OptionalAuthElement (workaround because it can't be mixed with AuthElement) 
  case object PWXAuthKey extends RequestAttributeKey[User]
  
  override def proceed[A](req: RequestWithAttributes[A])(f: RequestWithAttributes[A] => Future[SimpleResult]): Future[SimpleResult] = {
    implicit val (r, ctx) = (req, StackActionExecutionContext(req))
    restoreUser2 recover {
      case _ => Option.empty
    } flatMap {
      case Some(u) => super.proceed(req.set(PWXAuthKey, u))(f)
      case None => authenticationFailed(req)
    }
  }
  
  implicit def loggedInOpt[A](implicit req: RequestWithAttributes[A]): Option[User] = req.get(PWXAuthKey)
  
  private def restoreUser2(implicit request: RequestHeader, context: ExecutionContext): Future[Option[User]] = {
    val userIdOpt = for {
      cookie <- request.cookies.get(cookieName)
      token <- CookieUtil.verifyHmac(cookie)
      userId <- idContainer.get(token)
    } yield (token, userId)
    userIdOpt map { case (token, userId) =>
      resolveUser(userId) andThen {
        case Success(Some(_)) => idContainer.prolongTimeout(token, sessionTimeoutInSeconds)
      }
    } getOrElse {
      Future.successful(Option.empty)
    }
  }
  
  // END OF FORK OF OptionalAuthElement
  
}

Our PWXLoginLogoutController extends our PWXAuthController (which extends itself AuthElement). This allows to have both loggedIn and loggedInOpt methods available in the PWXLoginLogoutController trait. This is clearly a workaround but we are using this since a year without any bug. The problem is that we have to maintain this workaround with the evolution of the play2-auth plugin.

Your suggested solution seems to be more robust but also more complicated to implement. So we will wait for a more detailed and translated documentation before beginning to implement it ;)

Thank you very much !

thanks for workaround, @david-bouyssie

Since the reaction does not, I close this issue.
If there are any questions, please use gitter https://gitter.im/t2v/play2-auth :)

I have to say that it's not a very clean workaround because it's a fork of your code and I have to update my workaround for every new release of play2-auth.
This was the case yesterday when I updated my dependency to the latest version.
So if you have a better solution our team is still interested.

@david-bouyssie

the stackable-controller that play2-auth use in AuthElement and OptionalAuthElement compose action by every trait.
If you controll action composition by every method, you can use ActionBuilder that play2 standard action composition system.
And play2-auth provides some ActionBuilders, you can use AuthActionBuilders instead AuthElement.

thanks