Search code examples
sessionplayframeworksession-cookies

playframework - Can't read cookie from request


How can I get the cookie from a request in playframework? I have the following test endpoint

def home = Action.async { implicit request =>
    println(request)
    println(request.session)
    println(request.flash)
    request.session.get("session") match {
      case Some(cookie) => Future(Ok(cookie))
      case None =>
        Future(BadRequest(Json.obj("message" -> "missing session cookie")))
    }
  }

When submitting the following request:

curl 'http://local.example.com:9000/home' -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:76.0) Gecko/20100101 Firefox/76.0' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8' -H 'Accept-Language: en-US,en;q=0.5' --compressed -H 'Connection: keep-alive' -H 'Cookie: session=eyJhbGciOiJSUzI1NiIsImtpZCI...' -H 'Upgrade-Insecure-Requests: 1' -H 'Cache-Control: max-age=0'

I unfortunately get the "missing session cookie" response. and the following printout on the console

GET /home
Session(Map())
Flash(Map())

I don't know what I'm doing wrong. Any help is much appreciated.

Edit: I set the cookie using the following method:

def tokenLogin = Action(parse.json).async { implicit request =>
    val loginRequest = request.body.validate[LoginRequest]
    loginRequest.fold(
      errors =>
      {
        println(errors)
        Future(BadRequest(Json.obj("message" -> JsError.toJson(errors))))
      },
      request => {
        println("in success")
        firebaseAdminService
          .createSessionCookie(request.idToken)
          .map(sessionCookie =>
            Ok("success")
              .withNewSession
              .withCookies(Cookie(name = "session", value = sessionCookie))
          )
      }
    )
  }

Solution

  • By default, the session cookie in Play is called "PLAY_SESSION" (configuration play.http.session.cookieName).

    So, you would need to use -H "Cookie: PLAY_SESSION=..." with curl.

    But note, this won't work with arbitrary data since Play uses JWT and signs the information contained in the session cookie using its crypto secret.

    The only thing expected to work is using a session cookie received in a Set-Cookie header from your Play service in another request to the same service (having the same secret).


    update after your edit:

    When using request.session, you are accessing the session cookie, which is called PLAY_SESSION and the information stored inside it.

    But, you are setting a cookie of your own. This is something else.

    You can access "normal" cookies with

    request.cookies.get("session")
    

    Oh, and in case you really wanted to make use of the session cookie, you can set it like this:

    Ok("success").withSession("session" -> sessionCookie)