[Play 2.5 Scala]

289 views
Skip to first unread message

Henrik Kirk

unread,
Apr 1, 2016, 8:59:52 AM4/1/16
to play-framework
Upgrading from 2.4 to 2.5 a lot of my unittest broke. And especially one type I can't see to find a recommended way to solve.

I uses @helper.CSRF.formField to add CSRF token to my post request and when testing these in 2.4 I used a code a code like the one below.

"should require in id" in new Context {
      new WithApplication(application) {
        println("Require an id")
        val eventController = EventSpec.getEventController(application, env)
        val mnemonic = Mnemonic("first")

        val path = controllers.organizer.routes.Event.saveDetails(mnemonic).toString
        val request = FakeRequest(POST, path)
          .withSession("csrfToken" -> "438be706aaad4ad6c21529c947ae710e2ef86087-1459500808342-853383e7fe7bd398100b7e2b")
          .withFormUrlEncodedBody(
            "id" -> "",
            "name" -> "Update first",
            "date" -> "11/12-2016 14:00",
            "description" -> "A long description",
            "website" -> "www.google.com",
            "contact-email" -> "con...@event.com"
          )
          .withAuthenticator[CookieEnvironment](identityWithEvents.loginInfo)
        val result = eventController.saveDetails(mnemonic)(request)

        status(result) must beEqualTo(BAD_REQUEST)
      }
    }

After  upgrading I'm experiencing an exception when returning a BadRequest from my controller.

[error]    java.lang.RuntimeException: No CSRF token present! (CSRF.scala:29)
[error] views.html.helper.CSRF$$anonfun$2.apply(CSRF.scala:29)
[error] views.html.helper.CSRF$$anonfun$2.apply(CSRF.scala:29)
[error] views.html.helper.CSRF$.formField(CSRF.scala:29)
[error] views.html.organizer.event.detailsForm_Scope0$detailsForm_Scope1$detailsForm.apply(detailsForm.template.scala:31)

I've tried adding the csrfToken to the body which seem the way an request is send posting a request from a 'normal' browser but without luck.
I concluded (in my Event.saveDetails) this print statement 
println("tags --> "+request.tags)
has some extra informaion I can't recreate in my test.
tags --> Map(CSRF_TOKEN_RE_SIGNED -> 5699e0be647d05730d8fcf235b6ab25eb79f26bb-1459503234836-853383e7fe7bd398100b7e2b, ROUTE_COMMENTS -> , ROUTE_PATTERN -> /organizer/$mnemonic<[^/]+>/details, CSRF_TOKEN_NAME -> csrfToken, ROUTE_CONTROLLER -> controllers.organizer.Event, ROUTE_ACTION_METHOD -> saveDetails, CSRF_TOKEN -> e76844826c1b017bcb8274e81ed35d0899e6b847-1457968057499-853383e7fe7bd398100b7e2b, ROUTE_VERB -> POST)

So is tthere a guide to page I havn't found that descripes how to tests Post request with CSRF?

Best regards

Mariot Chauvin

unread,
Apr 1, 2016, 12:02:31 PM4/1/16
to play-fr...@googlegroups.com
Hi Henrik,
Did you have a look to CSRF changes in 2.5?
Hope this help,

Mariot

--
You received this message because you are subscribed to the Google Groups "play-framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to play-framewor...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/play-framework/fb923ef6-be95-4f51-a948-bae2517fce26%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



This e-mail and all attachments are confidential and may also be privileged. If you are not the named recipient, please notify the sender and delete the e-mail and all attachments immediately. Do not disclose the contents to another person. You may not use the information for any purpose, or store, or copy, it in any way.  Guardian News & Media Limited is not liable for any computer viruses or other material transmitted with or as part of this e-mail. You should employ virus checking software.
 
Guardian News & Media Limited is a member of Guardian Media Group plc. Registered Office: PO Box 68164, Kings Place, 90 York Way, London, N1P 2AP.  Registered in England Number 908396


Henrik Kirk

unread,
Apr 1, 2016, 1:34:10 PM4/1/16
to play-framework
Hey Mariot,

First of all sorry for the missing subject part.

And secondly thanks for answering. I have indeed been looking at bot the CSRF changes and ScalaCsrf, which seems fairly straigthforward but can't seem to get it to work. I've noticing the paragraph "Adding a CSRF token to the session" which states that it should be added to the session and of course to the post body, since im using a hidden field. So i have tried adding both 


.withSession("csrfToken" -> "438be706aaad4ad6c21529c947ae710e2ef86087-1459500808342-853383e7fe7bd398100b7e2b")


.withFormUrlEncodedBody(

  "csrfToken" -> "438be706aaad4ad6c21529c947ae710e2ef86087-1459500808342-853383e7fe7bd398100b7e2b",

   "id" -> "",
...


Also tried experimented with the header Csrf-Token = "nocheck" which of course didn't work. Guess the problem is that my csrfToken value in both session and body isn't picked up by the request, in the way I have structured my unittests, but works like a charm when testing the website.

Did I miss something in the Migration/ScalaCSRF notes somewhere.

Best regards

Greg Methvin

unread,
Apr 1, 2016, 4:25:27 PM4/1/16
to play-framework
Hi Henrik,

What does your action look like? Do you have a CSRF filter installed or does your action use the CSRFCheck or CSRFAddToken helpers?

Greg

--
You received this message because you are subscribed to the Google Groups "play-framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to play-framewor...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--
Greg Methvin
Senior Software Engineer

Henrik Kirk

unread,
Apr 2, 2016, 3:29:28 AM4/2/16
to play-framework
Hey Greg,

Thanks for helping me look into this.

I've created a simplified Github repository, which shows my basic setup and still have the issue when running the tests.

I'm using a basic filter

@Singleton

class Filters @Inject() (csrfFilter: CSRFFilter, securityHeadersFilter: SecurityHeadersFilter) extends HttpFilters {

  override def filters: Seq[EssentialFilter] = Seq(csrfFilter, securityHeadersFilter)

}


Hope you have time to look into this repository.

Best regards

On Friday, April 1, 2016 at 2:59:52 PM UTC+2, Henrik Kirk wrote:

Greg Methvin

unread,
Apr 3, 2016, 11:16:46 PM4/3/16
to play-framework
Hi Henrik,

You're calling the action method directly in the test, so the filters aren't being run. Since the filter isn't run, Play cannot generate/validate the token, which means when the form is rendered there is "no token present". Though you did pass the token in the session, it would not make sense for Play to render that in the form, since the token you want to use there is the one generated by the server.

If you want a workaround that doesn't involve running an app, you could just wrap your action in CSRFAddToken in the test:

      val csrfAddToken = app.injector.instanceOf[play.filters.csrf.CSRFAddToken]
      val action = csrfAddToken(homeController.saveDetails())
      val result = action(request)

--
You received this message because you are subscribed to the Google Groups "play-framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to play-framewor...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Henrik Kirk

unread,
Apr 4, 2016, 2:17:38 AM4/4/16
to play-framework
Hey Greg,

Thanks, works nicely. Will update the Githup repository to reflect your answer.

Thanks for taking the time.

Best regards

On Friday, April 1, 2016 at 2:59:52 PM UTC+2, Henrik Kirk wrote:

jez prime

unread,
Sep 12, 2016, 10:44:14 AM9/12/16
to Play Framework
I've got the same problem using tests written in Java. I'm trying to figure out how to apply the token addition to the Java API (Java action doesn't appear to be valid in put to csrfAddToken.aply).

I'm far from a Play expert - how do I convert a Java Action to a Scala Action instance so I can apply the csrfAddToken to it? Googling only seems to take me to application using the Scala API.

Thanks for any insight anyone can provide.

Cheers,

Jez
Reply all
Reply to author
Forward
0 new messages