Search code examples
javaplayframework

Play Framework CSRF error "[CSRF] Check failed because no token found in headers"


I'm new in Play Framework, and trying to submit the form, but get this error: "p.filters.CSRF - [CSRF] Check failed because no token found in headers" . I'm using Play 2.6, here's my controller code:

    package controllers;

import play.libs.Json;
import play.mvc.*;

import views.html.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class HomeController extends Controller {

    public Result index() {
        return ok(index.render("Your new application is ready."));
    }

    public Result test() {
        List<String> list = new ArrayList<>();
        list.add("Jobs");
        list.add("Work");
        list.add("Say");
        list.add("Stop");
        return ok(test.render("test", list));
    }

    public Result testPost() {
       Map<String,String[]> form =  request().body().asFormUrlEncoded();
       return ok(Json.toJson(form)).as("application/json");
    }

}

Template:

@(title: String, list: List[String])

@import helper._

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>@title</title>
    </head>
    <body>
        <form action="/test" method="post">
            <textarea name="raw_text">

            </textarea>
            @CSRF.formField
            <input type="submit" value="Submit" />
        </form>
    </body>
</html>

What I am doing wrong?


Solution

  • I couldn't find anything wrong with your code, so set up an identical Play project locally. When submitting the form I do not hit this issue. This is a base project created via:

    sbt new playframework/play-java-seed.g8
    

    Posting "Testing testing" as the content of the textArea returns the following Json (as displayed by browser):

    raw_text    
    0   "            Testing testing"
    csrfToken   
    0   "8fdc72b2d628e4fc0d8f6359f2ea247cc0f22e5c-1499016237415-3c043ab2a02c18020df21a1f"
    

    The one thing I took from my own projects, is a modified Filters class which looks like this:

    import play.mvc.EssentialFilter;
    import play.filters.cors.CORSFilter;
    import play.http.HttpFilters;
    import play.filters.csrf.CSRFFilter;
    import play.filters.headers.SecurityHeadersFilter;
    import java.util.List;
    import javax.inject.Inject;
    import javax.inject.Named;
    import java.util.Arrays;
    public class Filters implements HttpFilters {
        @Inject 
        CSRFFilter csrfFilter;
        @Inject
        CORSFilter corsFilter;
        @Inject 
        SecurityHeadersFilter secHeaders;
    
        @Override
        public List<EssentialFilter> getFilters() {
    
            return Arrays.<EssentialFilter>asList(new EssentialFilter[] { corsFilter.asJava(),secHeaders.asJava(), csrfFilter.asJava()});
                    }
    }
    

    Also my routes are as follows in conf/routes:

    # Map static resources from the /public folder to the /assets URL path
    GET     /assets/*file               controllers.Assets.versioned(path="/public", file: Asset)
    GET / controllers.HomeController.test()
    POST /test controllers.HomeController.testPost()
    

    Removing the @CSRF.formField caused a CSRF unauthorized just as for you.

    If you have any obvious differences with your setup I'd be happy to dig further but this seems to not be a direct problem with your code.