[Play 2.5.9 / 10] RuntimeException: No CSRF token present!]

1,253 views
Skip to first unread message

Jamiel

unread,
Nov 25, 2016, 9:13:36 PM11/25/16
to Play Framework
I am trying to use a global CSRF filter as per Play docs here. I am using Play 2.5.10 and 2.5.9 with the same outcome below.

I've setup the CSRF filter (The outcome occurs even if I remove the CORS filter):

    @Inject
    public Filters(Environment env , ExampleFilter exampleFilter, CORSFilter corsFilter, CSRFFilter csrfFilter) {
    super(corsFilter,csrfFilter);
        this.env = env;
        this.exampleFilter = exampleFilter;
        this.csrfFilter = csrfFilter;
    }

build.sbt is: 

libraryDependencies += filters


A GET retrieves a page with a form:

@helper.form(routes.SomeController.submitUpdated()){
 
@helper.CSRF.formField
}

However, loading the page with the form produces this

! @7270oaia5 - Internal server error, for (GET) [/abc/viewProfile?lid=2] ->
 
play
.api.http.HttpErrorHandlerExceptions$$anon$1: Execution exception[[CompletionException: java.lang.RuntimeException: No CSRF token present!]]
 at play
.api.http.HttpErrorHandlerExceptions$.throwableToUsefulException(HttpErrorHandler.scala:293)
 at play
.api.http.DefaultHttpErrorHandler.onServerError(HttpErrorHandler.scala:220)
 at play
.api.GlobalSettings$class.onError(GlobalSettings.scala:160)
 at play
.api.DefaultGlobal$.onError(GlobalSettings.scala:188)
 at play
.api.http.GlobalSettingsHttpErrorHandler.onServerError(HttpErrorHandler.scala:100)
 at play
.core.server.netty.PlayRequestHandler$$anonfun$2$$anonfun$apply$1.applyOrElse(PlayRequestHandler.scala:100)
 at play
.core.server.netty.PlayRequestHandler$$anonfun$2$$anonfun$apply$1.applyOrElse(PlayRequestHandler.scala:99)
 at scala
.concurrent.Future$$anonfun$recoverWith$1.apply(Future.scala:344)
 at scala
.concurrent.Future$$anonfun$recoverWith$1.apply(Future.scala:343)
 at scala
.concurrent.impl.CallbackRunnable.run(Promise.scala:32)
 at play
.api.libs.iteratee.Execution$trampoline$.execute(Execution.scala:70)
 at scala
.concurrent.impl.CallbackRunnable.executeWithValue(Promise.scala:40)
 at scala
.concurrent.impl.Promise$DefaultPromise.tryComplete(Promise.scala:248)
 at scala
.concurrent.Promise$class.complete(Promise.scala:55)
 at scala
.concurrent.impl.Promise$DefaultPromise.complete(Promise.scala:153)
 at scala
.concurrent.Future$$anonfun$recoverWith$1$$anonfun$apply$6.apply(Future.scala:344)
 at scala
.concurrent.Future$$anonfun$recoverWith$1$$anonfun$apply$6.apply(Future.scala:344)
 at scala
.concurrent.impl.CallbackRunnable.run(Promise.scala:32)
 at scala
.concurrent.BatchingExecutor$Batch$$anonfun$run$1.processBatch$1(BatchingExecutor.scala:63)
 at scala
.concurrent.BatchingExecutor$Batch$$anonfun$run$1.apply$mcV$sp(BatchingExecutor.scala:78)
 at scala
.concurrent.BatchingExecutor$Batch$$anonfun$run$1.apply(BatchingExecutor.scala:55)
 at scala
.concurrent.BatchingExecutor$Batch$$anonfun$run$1.apply(BatchingExecutor.scala:55)
 at scala
.concurrent.BlockContext$.withBlockContext(BlockContext.scala:72)
 at scala
.concurrent.BatchingExecutor$Batch.run(BatchingExecutor.scala:54)
 at scala
.concurrent.Future$InternalCallbackExecutor$.unbatchedExecute(Future.scala:599)
 at scala
.concurrent.BatchingExecutor$class.execute(BatchingExecutor.scala:106)
 at scala
.concurrent.Future$InternalCallbackExecutor$.execute(Future.scala:597)
 at scala
.concurrent.impl.CallbackRunnable.executeWithValue(Promise.scala:40)
 at scala
.concurrent.impl.Promise$DefaultPromise.scala$concurrent$impl$Promise$DefaultPromise$$dispatchOrAddCallback(Promise.scala:280)
 at scala
.concurrent.impl.Promise$DefaultPromise.onComplete(Promise.scala:270)
 at scala
.concurrent.Future$$anonfun$recoverWith$1.apply(Future.scala:344)
 at scala
.concurrent.Future$$anonfun$recoverWith$1.apply(Future.scala:343)
 at scala
.concurrent.impl.CallbackRunnable.run(Promise.scala:32)
 at akka
.dispatch.BatchingExecutor$AbstractBatch.processBatch(BatchingExecutor.scala:55)
 at akka
.dispatch.BatchingExecutor$BlockableBatch$$anonfun$run$1.apply$mcV$sp(BatchingExecutor.scala:91)
 at akka
.dispatch.BatchingExecutor$BlockableBatch$$anonfun$run$1.apply(BatchingExecutor.scala:91)
 at akka
.dispatch.BatchingExecutor$BlockableBatch$$anonfun$run$1.apply(BatchingExecutor.scala:91)
 at scala
.concurrent.BlockContext$.withBlockContext(BlockContext.scala:72)
 at akka
.dispatch.BatchingExecutor$BlockableBatch.run(BatchingExecutor.scala:90)
 at akka
.dispatch.TaskInvocation.run(AbstractDispatcher.scala:39)
 at akka
.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(AbstractDispatcher.scala:415)
 at scala
.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
 at scala
.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
 at scala
.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
 at scala
.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)
Caused by: java.util.concurrent.CompletionException: java.lang.RuntimeException: No CSRF token present!
 at java
.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:292)
 at java
.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:308)
 at java
.util.concurrent.CompletableFuture.uniApply(CompletableFuture.java:593)
 at java
.util.concurrent.CompletableFuture$UniApply.tryFire(CompletableFuture.java:577)
 at java
.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:474)
 at java
.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:1977)
 at scala
.concurrent.java8.FuturesConvertersImpl$CF.apply(FutureConvertersImpl.scala:21)
 at scala
.concurrent.java8.FuturesConvertersImpl$CF.apply(FutureConvertersImpl.scala:18)
 at scala
.concurrent.impl.CallbackRunnable.run(Promise.scala:32)
 at scala
.concurrent.BatchingExecutor$Batch$$anonfun$run$1.processBatch$1(BatchingExecutor.scala:63)
 at scala
.concurrent.BatchingExecutor$Batch$$anonfun$run$1.apply$mcV$sp(BatchingExecutor.scala:78)
 at scala
.concurrent.BatchingExecutor$Batch$$anonfun$run$1.apply(BatchingExecutor.scala:55)
 at scala
.concurrent.BatchingExecutor$Batch$$anonfun$run$1.apply(BatchingExecutor.scala:55)
 at scala
.concurrent.BlockContext$.withBlockContext(BlockContext.scala:72)
 at scala
.concurrent.BatchingExecutor$Batch.run(BatchingExecutor.scala:54)
 at scala
.concurrent.Future$InternalCallbackExecutor$.unbatchedExecute(Future.scala:599)
 at scala
.concurrent.BatchingExecutor$class.execute(BatchingExecutor.scala:106)
 at scala
.concurrent.Future$InternalCallbackExecutor$.execute(Future.scala:597)
 at scala
.concurrent.impl.CallbackRunnable.executeWithValue(Promise.scala:40)
 at scala
.concurrent.impl.Promise$DefaultPromise.tryComplete(Promise.scala:248)
 at scala
.concurrent.Promise$class.tryFailure(Promise.scala:112)
 at scala
.concurrent.impl.Promise$DefaultPromise.tryFailure(Promise.scala:153)
 at play
.api.mvc.Filter$$anon$1$$anonfun$apply$4$$anonfun$apply$1.applyOrElse(Filters.scala:83)
 at play
.api.mvc.Filter$$anon$1$$anonfun$apply$4$$anonfun$apply$1.applyOrElse(Filters.scala:77)
 
... 15 common frames omitted

I've confirmed my ExampleFilter is firing. 

Will Sargent

unread,
Nov 27, 2016, 9:31:31 PM11/27/16
to play-fr...@googlegroups.com
Try turning your play logger to TRACE in logback.xml, and checking that the csrfToken is being set appropriately in the request.

If you create a sample project from the seed:

```
sbt new playframework/play-java-seed.g8
```

and then create a controller from inside of SBT in that sample project:

```
g8scaffold form
```

then that should give you an example form and template already set up with CSRF.

--
Will Sargent
Engineer, Lightbend, Inc.


--
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-framework+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/play-framework/283dfc2b-1dbc-4801-a57e-d3328ddc691e%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Jamiel

unread,
Nov 28, 2016, 5:08:36 PM11/28/16
to Play Framework
Will,

I did exactly as you asked. In the seed app, I see the following in the trace

[trace] play.filters - [CSRF] Adding token to result: Result(200, Map(X-Frame-Options -> DENY, X-XSS-Protection -> 1; mode=block, X-Content-Type-Options -> nosniff, Content-Security-Policy -> default-src 'self', X-Permitted-Cross-Domain-Policies -> master-only))

I don't see anything like this occurring in my app. It seems like the CSRF filter is not even firing. The cookie doesn't show a CSRF value.  My app is using a submodule and both have filters added in build.sbt and everything else, from injecting the CSRF filter, to using the form helper methods, is identical to the seed app. I'm assuming there are only 3 steps in setting up the CSRF filter, namely adding filters to build.sbt, injecting the CSRFFilter in the constructor of the Filters class sitting in the root package and using @helper.CSRF.formField

Also, I notice the ExampleFilter in my app fired but doesn't add a header. It is coded as:

    @Override
   
public CompletionStage<Result> apply(
       
Function<RequestHeader, CompletionStage<Result>> next,
       
RequestHeader requestHeader) {
   
System.out.println("Filter fired");


       
return next.apply(requestHeader).thenApplyAsync(
            result
-> result.withHeader("X-ExampleFilter", "foo"),
           
exec
       
);
   
}

I do see "Filter fired" in my console but I do not see the X-ExampleFilter header. Also the example filter ceases to fire whatsoever if I remove entirely the following code from the Filters class.

    @Override
   
public EssentialFilter[] filters() {
     
// Use the example filter if we're running development mode. If
     
// we're running in production or test mode then don't use any
     
// filters at all.
     
if (env.mode().equals(Mode.DEV)) {
         
return new EssentialFilter[] { exampleFilter };
     
} else {
         
return new EssentialFilter[] {  };
     
}
   
}

In the seed app, the Filters class does not have the filters() method. 

So this is all a bit unclear. 1. Why would not the CSRF filter add the header, if configured correctly? 2. Why would the ExampleFilter fire but not add a header?

Is this a problem in the Play Framework? Or am I missing something?

Greg Methvin

unread,
Nov 28, 2016, 6:09:40 PM11/28/16
to play-framework
It's hard to tell without seeing the rest of your code, but maybe you are injecting `play.api.Environment` rather than `play.Environment`? In that case the if statement would always be false, since there are different types used for the mode in the Java and Scala APIs.

In the seed app, the Filters class does not have the filters() method.

This is because it extends DefaultHttpFilters, which has a varargs constructor accepting the array of filters. You can use either one. `DefaultHttpFilters` is ideal if you just want to pass the list of filters and don't want to do any logic.
 

So this is all a bit unclear. 1. Why would not the CSRF filter add the header, if configured correctly? 2. Why would the ExampleFilter fire but not add a header?

What does your actual code look like for your HttpFilters class? The code I see above doesn't include the CSRFFilter in the list of filters.

I'm not sure why it's not adding the header. It's possible it's being removed downstream by another filter but that doesn't seem likely.

Also, I would suggest explicitly defining the play.http.filters key:

play.http.filters=com.example.Filters

That way you can put Filters outside the root package and name it whatever you want. It's possible you are inadvertently doing this and not realizing it, which is why I generally suggest explicitly defining that configuration, instead of relying on Play to automatically find it on the classpath.

Can you add logs to the Filters class to make sure it's being created and the correct filters are being returned, and report back what you're seeing?


Is this a problem in the Play Framework? Or am I missing something?

--
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-framework+unsubscribe@googlegroups.com.

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



--
Greg Methvin
Senior Software Engineer

Jamiel

unread,
Nov 28, 2016, 7:42:52 PM11/28/16
to Play Framework
Greg, thanks for your response. I did confirm that Filters is using play.Environment instead of play.api.Environment. My main concern is the CSRFFilter, which is included as such:

import javax.inject.Inject;
import javax.inject.Singleton;


import play.Environment;
import play.Mode;
import play.filters.cors.CORSFilter;
import play.filters.csrf.CSRFFilter;
import play.http.DefaultHttpFilters;
import play.http.HttpFilters;
import play.mvc.EssentialFilter;


import filters.ExampleFilter;


/**
 * This class configures filters that run on every request. This
 * class is queried by Play to get a list of filters.
 *
 * Play will automatically use filters from any class called
 * <code>Filters</code> that is placed the root package. You can load filters
 * from a different class by adding a `play.http.filters` setting to
 * the <code>application.conf</code> configuration file.
 */

@Singleton
public class Filters extends DefaultHttpFilters implements HttpFilters {


   
private final Environment env;
   
private final EssentialFilter exampleFilter;
   
private final CSRFFilter csrfFilter;




   
/**
     * @param env Basic environment settings for the current application.
     * @param exampleFilter A demonstration filter that adds a header to
     */

   
@Inject
   
public Filters(Environment env , ExampleFilter exampleFilter, CORSFilter corsFilter, CSRFFilter csrfFilter) {

   
//super(corsFilter,csrfFilter);

       
this.env = env;
       
this.exampleFilter = exampleFilter;
       
this.csrfFilter = csrfFilter;
   
}



   
@Override

   
public EssentialFilter[] filters() {
     
// Use the example filter if we're running development mode. If
     
// we're running in production or test mode then don't use any
     
// filters at all.
     
if (env.mode().equals(Mode.DEV)) {
         
return new EssentialFilter[] { exampleFilter };
     
} else {
         
return new EssentialFilter[] {  };
     
}
   
}

I believe the CSRFFilter is part of the Play framework and doesn't need to be supplied by me. The form view that should place the CSRF field is

@helper.form(action = routes.SomeController.submitUpdate()){
 
@helper.CSRF.formField
}

Please let me know what additional code I can supply. I think I have all the pieces in place but am getting a [RuntimeException: No CSRF token present!] when displaying the form


Jamiel

unread,
Nov 28, 2016, 7:44:57 PM11/28/16
to Play Framework
This is the full exception: [CompletionException: java.lang.RuntimeException: No CSRF token present!]

Greg Methvin

unread,
Nov 28, 2016, 11:15:00 PM11/28/16
to play-framework
You need to include the CSRFFilter in the array of filters returned by filters(). That is most likely your problem. Also, if you are going to override filters() anyway, you don't need to extend DefaultHttpFilters.
 
I believe the CSRFFilter is part of the Play framework and doesn't need to be supplied by me.

Is there a particular reason you thought that? Perhaps the documentation could be improved. Adding the filters dependency just adds it to your classpath; it doesn't change how your application is configured.
 
The form view that should place the CSRF field is

@helper.form(action = routes.SomeController.submitUpdate()){
 
@helper.CSRF.formField
}

Please let me know what additional code I can supply. I think I have all the pieces in place but am getting a [RuntimeException: No CSRF token present!] when displaying the form

The helper doesn't work without a CSRF filter installed. The technical reason for this is that the CSRF filter generates the token first and adds it as a tag to the request and to the cookie. The formField helper then retrieves this tag from the implicit 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-framework+unsubscribe@googlegroups.com.

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

Jamiel

unread,
Nov 28, 2016, 11:26:14 PM11/28/16
to Play Framework
I believe the CSRF filter is supplied by Play Framework based on the docs here stating "Play provides a global CSRF filter that can be applied to all requests" and is part of the play.filters.csrf package.  Am I mistaken? If so, how do I supply a CSRF filter? 

The CSRSFilter supplied in Play is not of type EssentialFilter so I am not clear how it gets passed back from filters()

To unsubscribe from this group and stop receiving emails from it, send an email to play-framewor...@googlegroups.com.

Jamiel

unread,
Nov 28, 2016, 11:49:48 PM11/28/16
to Play Framework
The ExampleFilter is functioning, I had super() commented out in Filters' constructor. However, the CSRFFilter stil throws the same exception.

Greg Methvin

unread,
Nov 29, 2016, 1:21:07 AM11/29/16
to play-framework
On Mon, Nov 28, 2016 at 8:26 PM, Jamiel <i...@jamiel.net> wrote:
I believe the CSRF filter is supplied by Play Framework based on the docs here stating "Play provides a global CSRF filter that can be applied to all requests" and is part of the play.filters.csrf package.  Am I mistaken? If so, how do I supply a CSRF filter? 

Play provides the filter, but it doesn't configure your app to use it by default. You have to return it in the list of filters in your HttpFilters class.

You usually also want to configure ordering with respect to the other filters, or disable them in some environments (like you did with ExampleFilter), and that's much easier to do if you have to specify them all explicitly.

The example in the documentation shows how to supply it by extending DefaultHttpFilters. You could do something similar here:

public class Filters extends DefaultHttpFilters {
    @Inject public Filters(CSRFFilter csrfFilter, ExampleFilter exampleFilter) {
      super(csrfFilter, exampleFilter);
    }
}

And it's just a varargs method so you can do whatever logic you want and pass the array directly to the constructor.

Note that the varargs constructor of DefaultHttpFilters accepts play.api.mvc.EssentialFilter (Scala API) not play.mvc.EssentialFilter (Java API), so it works with all the filters provided by Play without needing to convert them to the Java EssentialFilter.

The alternative is to extend play.mvc.HttpFilters and override the filters method, and include the csrfFilter in there, but since it returns play.mvc.EssentialFilter, which is Java API, so you need to convert it:

public EssentialFilter[] filters() {
  return new EssentialFilter[] { csrfFilter.asJava, exampleFilter };
}

The CSRSFilter supplied in Play is not of type EssentialFilter so I am not clear how it gets passed back from filters()

I think this is probably the source of your confusion then. The filters provided by Play are only implemented on the Scala API, so you have to call .asJava to convert them, OR use the special varargs constructor of DefaultHttpFilters to do the conversion for you as shown in the docs.

Does that all make sense?

To unsubscribe from this group and stop receiving emails from it, send an email to play-framework+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/play-framework/c667e24a-03aa-4784-a4d7-716e6502a88e%40googlegroups.com.

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

Jamiel

unread,
Nov 29, 2016, 9:12:03 AM11/29/16
to Play Framework
returning CSRFilter.asJava() did the trick, as per Greg. Thank you Greg and Will.


On Friday, November 25, 2016 at 9:13:36 PM UTC-5, Jamiel wrote:
Reply all
Reply to author
Forward
0 new messages