Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Expected CSRF token not found. Has your session expired 403

Tags:

java

spring

I'm trying to write my test spring security application with mkyong examples.

Spring Security: 4.0.0.RC1
Spring: 4.1.4.RELEASE

I have the following security config:

<http auto-config="true">
    <intercept-url pattern="/admin**" 
                    access="hasRole('ADMIN')"/>
    <form-login authentication-failure-url="/?auth_error" 
                        username-parameter="user" 
                        password-parameter="password" 
                        login-page="/"
                        default-target-url="/?OK"/>
<!-- <csrf/> -->
</http>

<authentication-manager>
    <authentication-provider>
        <user-service>
            <user name="mkyong" password="123456" authorities="ADMIN" />
        </user-service>
    </authentication-provider>
</authentication-manager>

login-page:

<html>
<body>
<form method="POST">
    <label for="user">User: </label>
    <input type="text" id="user" name="user" /> </br>
    <label for="password">Password: </label>
    <input type="text" name="password" id="password" /> </br>
    <input type="submit" /> 
</form>
</body>
</html>

Now, when I try to login I get 403 error page:

Invalid CSRF Token 'null' was found on the request parameter 
'_csrf' or header 'X-CSRF-TOKEN'.

description:

Access to the specified resource (Invalid CSRF Token 'null' was
found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'.) has been 
forbidden.

What's wrong, how can I fix that? I commented csrf in the config, but the error-message has to do with the csrf.

like image 298
St.Antario Avatar asked Jan 25 '15 16:01

St.Antario


People also ask

Do CSRF tokens expire?

If a client posts a request and the cross-site request forgery (CSRF) token in the OData cookie store has expired, the token cannot be validated, and the client receives a 403 error.

What is CSRF token?

A CSRF token is a secure random token (e.g., synchronizer token or challenge token) that is used to prevent CSRF attacks. The token needs to be unique per user session and should be of large random value to make it difficult to guess. A CSRF secure application assigns a unique CSRF token for every user session.


6 Answers

I had the same problem. I use thymeleaf and Spring boot, and got the CSRF token issue when I try to post data in a form.

Here is my working solution:

  1. Add this hidden input:

    <input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />

  2. In your WebSecurityConfig (which extends WebSecurityConfigurerAdapter), add a method:

    private CsrfTokenRepository csrfTokenRepository() 
    { 
        HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository(); 
        repository.setSessionAttributeName("_csrf");
        return repository; 
    }
    

    and add code in method configure():

    @Override
     protected void configure(HttpSecurity http) throws Exception {
         http.csrf()
         .csrfTokenRepository(csrfTokenRepository())
    

I spent lot of time on this problem. Hope it can help someone who has the same problem.

like image 74
Yinghua Avatar answered Sep 25 '22 08:09

Yinghua


If you must disable it...

In Spring Security 4, CSRF is enabled by default when using the XML configuration. Previously it was only enabled by default for the Java-based configuration.

According to Section 14.4.2 of the Spring Security Documentation:

As of Spring Security 4.0, CSRF protection is enabled by default with XML configuration. If you would like to disable CSRF protection, the corresponding XML configuration can be seen below.

<http>
   ...
   <csrf disabled="true"/>
   ...
</http>
like image 44
Todd Avatar answered Sep 22 '22 08:09

Todd


Disabling CSRF protection sounds like a bad idea, no?

If you use Spring's Form Tag library the CSRF token will be automatically included. It will also HTML Escape form element values, which makes your site safer against XSS, and more correct.

<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %> 

<form:form>
  <form:input...
</form:form>

Otherwise, add this to your form:

<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
like image 22
Neil McGuigan Avatar answered Sep 23 '22 08:09

Neil McGuigan


To @St.Antario, Please use this code to enable CSRF in your code

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .antMatcher("*/*").authorizeRequests()
                .antMatchers("/", "/login**").permitAll()
                .anyRequest().authenticated()
                .and().csrf().csrfTokenRepository(csrfTokenRepository())
                .and().addFilterAfter(csrfHeaderFilter(), SessionManagementFilter.class);
    }

    private Filter csrfHeaderFilter() {
        return new OncePerRequestFilter() {

            @Override
            protected void doFilterInternal(HttpServletRequest request,
                                            HttpServletResponse response,
                                            FilterChain filterChain) throws ServletException, IOException {

                CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
                if (csrf != null) {
                    Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
                    String token = csrf.getToken();
                    if (cookie == null || token != null
                            && !token.equals(cookie.getValue())) {

                        // Token is being added to the XSRF-TOKEN cookie.
                        cookie = new Cookie("XSRF-TOKEN", token);
                        cookie.setPath("/");
                        response.addCookie(cookie);
                    }
                }
                filterChain.doFilter(request, response);
            }
        };
    }

    private CsrfTokenRepository csrfTokenRepository() {
        HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
        repository.setHeaderName("X-XSRF-TOKEN");
        //repository.setSessionAttributeName(("X-XSRF-TOKEN"));
        return repository;
    }
}
like image 43
Java_Fire_Within Avatar answered Sep 23 '22 08:09

Java_Fire_Within


spring-security.xml

<beans:beans xmlns="http://www.springframework.org/schema/security"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:beans="http://www.springframework.org/schema/beans"
             xsi:schemaLocation="
    http://www.springframework.org/schema/security 
    http://www.springframework.org/schema/security/spring-security.xsd
    http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans.xsd">

    <http pattern="/resources/**" security="none" />

    <http use-expressions="true">
        <intercept-url pattern="/login*" access="isAnonymous()" />
        <intercept-url pattern="/**" access="isAuthenticated()"/>
        <form-login
            login-page="/login"
            default-target-url="/home"
            authentication-failure-url="/login?error=true" /> 
        <logout
            logout-success-url="/login"
            delete-cookies="JSESSIONID" />
    </http>
    <authentication-manager>
        <authentication-provider>
            <user-service>
                <user name="carlos" password="123" authorities="ROLE_USER" />
            </user-service>
        </authentication-provider>
    </authentication-manager>
</beans:beans>

web.xml

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/applicationContext.xml, /WEB-INF/spring-security.xml</param-value>
</context-param>

add add jsp login

<%@page session="true"%>

and input hidden:

<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
like image 40
Carlos Alberto Gonzalez Avatar answered Sep 26 '22 08:09

Carlos Alberto Gonzalez


What is your login page named Is it ending with .jsp

If the login page is not ending with .jsp Spring framework doesn't evaluate the JSP or EL expressions

like image 29
BJ5 Avatar answered Sep 26 '22 08:09

BJ5