I am writing a method to set the session cookie properly after a user authenticates. Setting the cookies as follows does not work. The following snippet results in an error with the 'withSession' call:
Overloaded method value [withSession] cannot be applied to ((String, Long))
Code:
/**
* Process login form submission.
*/
def authenticate = Action { implicit request =>
loginForm.bindFromRequest.fold(
formWithErrors => BadRequest(views.html.login(formWithErrors)),
credentials => {
val user = models.User.findByEmail(credentials._1)
user match {
case Some(u) => {
Redirect(routes.Dashboard.index).withSession(Security.username -> u.id)
}
case None => Redirect(routes.Auth.login)
}
}
)
}
'credentials' is simply a tuple with the email and password submitted by the user. If I get rid of 'withSession' part then it runs fine. If I move the 'Redirect' statement out of the pattern matching code then is works fine. Why does it not work as I have it above and how do I fix it?
I think withSession expects a String, String
Have a look at http://www.playframework.org/documentation/api/2.0.3/scala/index.html#play.api.mvc.SimpleResult
def withSession(session: (String, String)*): PlainResult = withSession(Session(session.toMap))
Related
I am trying to add authentication to my Play Framework single page app.
What I would like to have is something like:
def unsecured = Action {
Ok("This action is not secured")
}
def secured = AuthorizedAction {
// get the authenticated user's ID somehow
Ok("This action is secured")
}
For a traditional web app, I had previously done this, following Play Framework docs:
def authenticate = Action { implicit request =>
loginForm.bindFromRequest.fold(
formWithErrors => BadRequest(views.html.login(formWithErrors)),
user => {
Redirect(routes.Application.home).withSession(Security.username -> user._1)
}
)
}
def logout = Action {
Redirect(routes.Auth.login).withNewSession.flashing(
"success" -> "You are now logged out."
)
}
and the Authorized Action is extending ActionBuilder as follows:
object AuthorizedAction extends ActionBuilder[Request] with Results {
/**
* on auth success: proceed with the request
* on auth failure: redirect to login page with flash
*/
def invokeBlock[A](request: Request[A], block: (Request[A]) => Future[Result]) = {
// TODO: is "isDefined" enough to determine that user is logged in?
if(request.session.get("username").isDefined) {
block(request)
}
else {
Future.successful(Redirect(routes.Auth.login).flashing(
"failure" -> "You must be logged in to access this page."
))
}
}
}
For single page applications however, this approach doesn't exactly work anymore.
This article by James Ward explains how the new approach is to be designed, and includes a Java implementation:
Securing SPA and rest services
The implementation was redone in Scala by Marius Soutier: Securing SPA in Scala
In his example, he implements a Security trait:
trait Security { self: Controller =>
val cache: CacheApi
val AuthTokenHeader = "X-XSRF-TOKEN"
val AuthTokenCookieKey = "XSRF-TOKEN"
val AuthTokenUrlKey = "auth"
/** Checks that a token is either in the header or in the query string */
def HasToken[A](p: BodyParser[A] = parse.anyContent)(f: String => Long => Request[A] => Result): Action[A] =
Action(p) { implicit request =>
val maybeToken = request.headers.get(AuthTokenHeader).orElse(request.getQueryString(AuthTokenUrlKey))
maybeToken flatMap { token =>
cache.get[Long](token) map { userid =>
f(token)(userid)(request)
}
} getOrElse Unauthorized(Json.obj("err" -> "No Token"))
}
}
Functions are now secured like this instead of a plain Action:
def ping() = HasToken() { token => userId => implicit request =>
user.findByID (userId) map { user =>
Ok(Json.obj("userId" -> userId)).withToken(token -> userId)
} getOrElse NotFound (Json.obj("err" -> "User Not Found"))
}
where .withToken is defined as:
implicit class ResultWithToken(result: Result) {
def withToken(token: (String, Long)): Result = {
cache.set(token._1, token._2, CacheExpiration)
result.withCookies(Cookie(AuthTokenCookieKey, token._1, None, httpOnly = false))
}
def discardingToken(token: String): Result = {
cache.remove(token)
result.discardingCookies(DiscardingCookie(name = AuthTokenCookieKey))
}
}
I am not liking how complex the "ping" function above has become, and would have preferred to use an Action Builder (like the first example), where auth failure is caught and dealt with at a single point. (as of now, if I want to secure functions ping2 and ping3, each one has to check whether the user is found and deal with the "not found" case)
I have tried to put together an action builder, inspired by Marius' implementation, most particularly his use of the cacheApi which is necessary.
However the AuthorizedAction is an object, and cacheApi needs to be injected (so need to change the object to singleton class), or cannot be declared in an object without being defined.
I also feel like the AuthorizedAction needs to remain an object, in order to be used as:
def secured = AuthorizedAction {
Would anyone please clear up the confusion, and possibly help with some implementation details?
Thanks a lot
The simplest way in my opinion is to go with ActionBuilder. You can define an action builder as a class (and pass it some dependencies) or as an object.
First you'll need to define a type a request that will contain the information about the user:
// You can add other useful information here
case class AuthorizedRequest[A](request: Request[A], user: User) extends WrappedRequest(request)
Now define your ActionBuilder
class AuthorizedAction(userService: UserService) extends ActionBuilder[AuthorizedRequest] {
override def invokeBlock[A](request: Request[A], block: (AuthorizedRequest[A]) ⇒ Future[Result]): Future[Result] = {
request.headers.get(AuthTokenHeader).orElse(request.getQueryString(AuthTokenUrlKey)) match {
case Some(token) => userService.findByToken(token).map {
case Some(user) =>
val req = AuthorizedRequest(request, user)
block(req)
case None => Future.successful(Results.Unauthorized)
}
case None => Future.successful(Results.Unauthorized)
}
}
}
Now you can use it in your controller:
val authorizedAction = new AuthorizedAction(userService)
def ping = authorizedAction { request =>
Ok(Json.obj("userId" -> request.user.id))
}
I am building an Application using PlayFramework / Scala.
For my security layer I am using Auth0 which is working fine for the main page, and I am already able to get profile information / add new users etc.
Now I have an API and I want to let people use it only when they are connected as well so I added this custom Action on my API controller :
def AuthenticatedAction(f: Request[AnyContent] => Future[Result]): Action[AnyContent] = {
Action.async { implicit request =>
(request.session.get("idToken").flatMap { idToken =>
cache.get[JsValue](idToken + "profile")
} map { profile =>
f(request) // IF USER CONNECTED THEN ADD PROFILE TO REQUEST AND PROCEED
}).orElse {
Some(Future(Redirect("/login"))) // OTHERWISE REDIRECT TO LOGIN PAGE
}.get
}
}
I am able to use it for my read action (returning only one record by ID) :
def read(entityName: String, id: String) = AuthenticatedAction {
// SOME NOT RELEVANT CODE
}
My problem comes when I try to send json to create an object :
This was my code working before I tried to add a custom authenticated action :
def store(entityName: String, id: String) = Action.async(parse.json) {
// SOME NOT RELEVANT CODE
}
Now I was expecting to use
def store(entityName: String, id: String) = AuthenticatedAction(parse.json) {
// SOME NOT RELEVANT CODE
}
Here is the compile error :
type mismatch; found : play.api.mvc.BodyParser[play.api.libs.json.JsValue]
required: play.api.mvc.Request[play.api.mvc.AnyContent] ⇒ scala.concurrent.Future[play.api.mvc.Result]
And I know it comes from the fact that I do not support passing custom body parsers, I have looked into using ActionBuilder from the docs as well but I am trying to use the code provided by Auth0.
Is there a way to handle custom parsers when the custom action is not defined as a class ?
So I just found a solution !
I noticed Action async has actually 2 different signatures :
async[A](bodyParser: BodyParser[A])(block: (R[A]) ⇒ Future[Result]): Action[A]
and
async(block: ⇒ Future[Result]): Action[AnyContent]
So I just added another AuthenticationAction on my part
def AuthenticatedAction[A](b: BodyParser[A])(f: Request[A] => Future[Result]): Action[A] = {
Action.async(b) { implicit request =>
(request.session.get("idToken").flatMap { idToken =>
cache.get[JsValue](idToken + "profile")
} map { profile =>
f(request) // IF USER CONNECTED THEN ADD PROFILE TO REQUEST AND PROCEED
}).orElse {
Some(Future(Redirect("/login")))
}.get
}
}
There is Security Example where you can find => implicit request for def withUser(... method.
Based on that example I've created one-file-sample here:
https://github.com/Sergey80/scala-samples/blob/master/src/main/scala/implicits/usecases/RequestResponseTest.scala (where is no implicit .. and I do not see why I need use it)
The question is:
why do I need type implicit request (as was shown in Security Example) if it works without implicit. Since we are already referring on requestas val (defined above in the code).
Copy-pasting my simplified-sample here (where not implicit is used), this code has the same functions as in initial Security Example (withUser, withAtuh) with same set of parameters, the point was just to make it launchable from one file:
package implicits.usecases
object RequestResponseTest extends App {
type User = String // for simplicity sake - all are strings
type Request = String
type Result = String
trait Action // there are two auth Action - Ok and Not Ok
case class OkAction(content:Result) extends Action
case class UnauthorizedAction(content:Result) extends Action
var userDB = List("user1", "user2", "user3") // our simple database
val user = "user1" // usually user available from the session
var request : Request = "request" // current request
// check authorization and wraps request into Action
def withAuth(f: User => (Request => Result) ): Action = {
println("withAuth in play...")
val result:Result = f("user1")(request) // (is user was found or not)
def isAuthorized(user:User): Boolean = {
println("check authorisation...")
true // authorize everyone, welcome :)
}
def onUnAuthorized(request: Request): Action = {
println("wrapped to Action as not authorized")
UnauthorizedAction(request)
}
if (result == "ok") {
if (isAuthorized(request)) {
println("wrapped to Action as authorized")
OkAction(request)
} else onUnAuthorized(request)
} else onUnAuthorized(request)
}
//
def withUser(f: User => (Request => Result)) : Action = {
println("withUser in play...")
def findInDb(user: User): Option[User] = {
userDB.find(u => u == user)
}
val authResult:Action = withAuth ( // call 'withAuth'
/* Create anonymous function to please the 'withAuth'
it is already known who is current user, and what request is, but doesn't what Result is.
And he Result is the fact whether the user exists in users database or not.
So it tries to get the Result by searching for the current user.
If user has been found then it makes sense to continue with Authorisation (withAuth)
*/
user => request => { // passing anonymous function with user, request, and result (where result is based on user existence in the user db )
val userOption = findInDb("user1") // find the user in users db
val result:Result = userOption match { // check if user exists
case Some(_) => // user has been found
println("user has been found")
"ok"
case None => // user has not been found
println("user has not been found")
"not ok"
}
result // "ok" / "not ok" (user has been found or not)
} // end of passing anonymous function to 'withAuth'
)
authResult match {
case OkAction(_) => f(user)(request) // if authorized do The work
}
authResult
} // edn of 'withUser'
// Let's run this and to some work (no `implicit request` here)
def doWork() = withUser { // doWork -> withUser -> withAuth (like Decorator/Wrapper pattern)
user => request => {
// if user exists (withUser) and authorization is ok (withAuth), then this work will done
println("do some important work here!!")
"work is done!" // Result is just a String
}
}
val result = doWork() // doWork doesn't care about user or request
}
/* Output:
withUser in play...
withAuth in play...
user has been found
check authorisation...
wrapped to Action as authorized
do some important work here!!
*/
Update:
I understand if implicit was put on type Request to let compiler look up for value of this type which is defined implicitly somewhere. Like Inversion of Control injection. But there in Security Example it is put on value itself. On "request" value. If I'm putting 'request' it automatically means that I already have access to it and compiler knows about it (without implicit).
One word answer: convenience.
Let's take this simple example from your first link:
def login = Action { implicit request =>
Ok(views.html.login(loginForm))
}
You probably don't need the implicit here, but it's often convenient to have. Here's why:
This is really calling Action.apply. In particular, an overload that accepts a parameter:
block: Request[A] => Result
The block being passed here is the anonymous function:
request => Ok(views.html.login(loginForm))
The Request is probably not being used at all here, so whether it's implicit or not doesn't really matter. However, Play has many functions which require an implicit Request (for i18n, checking the uri accessed, whether or not a secure path was used, etc).
If views.html.login (a Play view) requires an implicit Request parameter, then it would be very useful to mark request as implicit, which we have the option of doing so.
implicit request => Ok(views.html.login(loginForm))
All the above code is doing is creating an anonymous function Request[A] => Result, in which the Request[A] parameter is made implicit. It isn't looking for an implicit, it's creating one. Similar to:
def anon(req: Request[A]): Result = {
implicit val request = req
Ok(views.html.login(loginForm)
}
Why? It makes for a much less boiler-plate, especially when many methods within the block require Request parameters. There's also no ambiguity, because the implicit is contained within the block of the anonymous function, and in this example, there is only one Request that each method should receive (there's only method call in this example, but there could be several more).
Otherwise you'd have to write:
def login = Action { request =>
Ok(views.html.login(loginForm)(request))
}
The withUser example isn't really any different. It just involves another nested anonymous function where request is made implicit.
This simple snippet explained me the thing (let me remember). Kind of essential:
implicit val integer = 3
def function4(implicit i:Int) = i // this works as default variable (ALMOST)
// same as this
def function4_1(i:Int = implicitly[Int]) = i // implicit scope has Int = 3
val result4 = function4 // should be without ()
val result4_1 = function4_1() // requires ()
println("result4: " + result4) // 3
println("result4_1: " + result4_1) // 3
Also I've prepared couple examples here: 1 2 (2 - improving my initial code with Request-Response case)
Please take a look at the following code
Application.scala
def Online = Action { implicit request =>
loginForm.bindFromRequest.fold(
formWithErrors => BadRequest(html.login(formWithErrors)),
user => Contact.AddOnline("email" -> user._1)
)
followed by
trait Secured {
/**
* Retrieve the connected user email.
*/
private def username(request: RequestHeader) =
request.session.get("email")
/**
* Redirect to login if the user in not authorized.
*/
private def onUnauthorized(request: RequestHeader) =
Home.flashing("failure"->"You are not logged in");
// --
/**
* Action for authenticated users.
*/
def IsAuthenticated(f: => String => Request[AnyContent] => Result)=
Security.Authenticated(username, onUnauthorized) { user =>
Action(request => f(user)(request))
}
--
My Problem is I am trying to call a piece of code called setOnline(user.email). This code sets a certain user's status as online only after he is authenticated. In the above given code I would like to call my setOnline(user.email) function but I am not sure where or how I should call. I have been trying for the past 4 hours without any luck. The main problem is I do not understand how the above piece of code works completely (as it is not my code).
This code....
def Online = Action { implicit request =>
loginForm.bindFromRequest.fold(
formWithErrors => BadRequest(html.login(formWithErrors)),
user => Contact.AddOnline("email" -> user._1)
)
is an action that binds a request to a Form object called loginForm. It will check to see if the form has errors, if it does then it will display the form with those errors. If not, then it will invoke Contact.AddOnline.
And this...
def IsAuthenticated(f: => String => Request[AnyContent] => Result) =
Security.Authenticated(username, onUnauthorized) { user =>Action(request => f(user)(request))
is an Action that wraps itself around another action (action composition) to determine if the given username is authenticated or not. If it is not authorized, then it will invoke the "onUnauthorized" function which will flash "You are not logged in". Which in reality will not work. You should write your "onUnauthorized" similar to this...
private def onUnauthorized(request: RequestHeader) =
Redirect(routes.Home.url).flashing("You are not logged in")
I have a route that is type "POST". I am sending post data to the page. How do I access that post data. For example, in PHP you use $_POST
How do I access the post data in scala and play framework?
As of Play 2.1, there are two ways to get at POST parameters:
1) Declaring the body as form-urlencoded via an Action parser parameter, in which case the request.body is automatically converted into a Map[String, Seq[String]]:
def test = Action(parse.tolerantFormUrlEncoded) { request =>
val paramVal = request.body.get("param").map(_.head)
}
2) By calling request.body.asFormUrlEncoded to get the Map[String, Seq[String]]:
def test = Action { request =>
val paramVal = request.body.asFormUrlEncoded.get("param").map(_.head)
}
Here you've got good sample how it's done in Play:
https://github.com/playframework/Play20/blob/master/samples/scala/zentasks/app/controllers/Application.scala
val loginForm = Form(
tuple(
"email" -> text,
"password" -> text
) verifying ("Invalid email or password", result => result match {
case (email, password) => User.authenticate(email, password).isDefined
})
)
/**
* Handle login form submission.
*/
def authenticate = Action { implicit request =>
loginForm.bindFromRequest.fold(
formWithErrors => BadRequest(html.login(formWithErrors)),
user => Redirect(routes.Projects.index).withSession("email" -> user._1)
)
}
It's described in the documentation of the forms submission
as #Marcus points out, bindFromRequest is the preferred approach. For simple one-off cases, however, a field
<input name="foo" type="text" value="1">
can be accessed via post'd form like so
val test = Action { implicit request =>
val maybeFoo = request.body.get("foo") // returns an Option[String]
maybeFoo map {_.toInt} getOrElse 0
}
Here you've got good sample how it's done in Play 2:
def test = Action(parse.tolerantFormUrlEncoded) { request =>
val paramVal = request.body.get("param").map(_.head).getorElse("");
}