Haseeb Wali
Haseeb Wali

Reputation: 1171

Could not verify the provided CSRF token because your session was not found in spring security

I am using spring security along with java config

@Override
protected void configure(HttpSecurity http) throws Exception { 
    http
    .authorizeRequests()
    .antMatchers("/api/*").hasRole("ADMIN")
    .and()
    .addFilterAfter(new CsrfTokenResponseHeaderBindingFilter(), CsrfFilter.class)
    .exceptionHandling()
    .authenticationEntryPoint(restAuthenticationEntryPoint)
    .and()
    .formLogin()
    .successHandler(authenticationSuccessHandler)
    .failureHandler(new SimpleUrlAuthenticationFailureHandler());

I am using PostMan for testing my REST services. I get 'csrf token' successfully and I am able to login by using X-CSRF-TOKEN in request header. But after login when i hit post request(I am including same token in request header that i used for login post request) I get the following error message:

HTTP Status 403 - Could not verify the provided CSRF token because your session was not found.

Can any one guide me what I am doing wrong.

Upvotes: 48

Views: 94015

Answers (8)

Tommly Jumah
Tommly Jumah

Reputation: 70

im late but for anyone who still needs its add @CrossOrigin("*") in your controller classes

Upvotes: -1

Parthanaux
Parthanaux

Reputation: 135

This is an old question but this might help someone. I had the similar issue and this is how I was able to resolve it.

In order for the CSRF to work with the REST API you need to obtain a CSRF token via API before every single call and use that token. Token is different every time and cannot be re-used.

Here is the controller to get the CSRF token:

@RequestMapping(value = "/csrf", method = RequestMethod.GET)
    public ResponseEntity<CSRFDTO> getCsrfToken(HttpServletRequest request) {
        CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
        return ResponseEntity.ok(CSRFDTO.builder()
                .headerName(csrf.getHeaderName())
                .token(csrf.getToken())
                .build());
    }

Additionally, you might consider configuring your Spring app to disable the CSRF for the REST API endpoints. To quote an article I've read somewhere:

I'm very certain that CSRF tokens on a REST endpoint grant zero additional protection. As such, enabling CSRF protection on a REST endpoint just introduces some useless code to your application, and I think it should be skipped.

Hope this helps.

Upvotes: 0

Georgios Syngouroglou
Georgios Syngouroglou

Reputation: 19944

I get this error message (HTTP Status 403 - Could not verify the provided CSRF token because your session was not found.) when I do a JS fetch AJAX call without using the credentials: "same-origin" option.

Wrong way

fetch(url)
.then(function (response) { return response.json(); })
.then(function (data) { console.log(data); })

Correct way

fetch(url, {
    credentials: "same-origin"
})
.then(function (response) { return response.json(); })
.then(function (data) { console.log(data); })

Upvotes: 0

Dmitri Algazin
Dmitri Algazin

Reputation: 3456

Came to same error just with POST methods, was getting 403 Forbidden "Could not verify the provided CSRF token because your session was not found."

After exploring some time found solution by adding @EnableResourceServer annotation to config.

Config looks like that (spring-boot.version -> 1.4.1.RELEASE, spring-security.version -> 4.1.3.RELEASE, spring.version -> 4.3.4.RELEASE)

@Configuration
@EnableWebSecurity
@EnableResourceServer
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends ResourceServerConfigurerAdapter {

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
  auth.userDetailsService(inMemoryUserDetailsManager()).passwordEncoder(passwordEncoder());
}

@Override
public void configure(HttpSecurity http) throws Exception {
    http.httpBasic();
    http.sessionManagement().sessionCreationPolicy(STATELESS);
    http.csrf().disable();
    http.authorizeRequests().anyRequest()
            .permitAll();
}

private InMemoryUserDetailsManager inMemoryUserDetailsManager() throws IOException {
    // load custom properties
    Properties properties = new Properties();
    return new InMemoryUserDetailsManager(properties);
}

private PasswordEncoder passwordEncoder() {
    return new TextEncryptorBasedPasswordEncoder(textEncryptor());
}

private TextEncryptor textEncryptor() {
    return new OpenSslCompatibleTextEncryptor();
}

}

Upvotes: 2

GuoJunjun
GuoJunjun

Reputation: 331

try this: @Override protected boolean sameOriginDisabled() { return true;}

@Configuration
public class WebSocketSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {

    ...

    // Determines if a CSRF token is required for connecting. This protects against remote
    // sites from connecting to the application and being able to read/write data over the
    // connection. The default is false (the token is required).
    @Override
    protected boolean sameOriginDisabled() {
        return true;
    }
}

source: WebSocket Security: Disable CSRF within WebSockets

Upvotes: 6

Dario Seidl
Dario Seidl

Reputation: 4620

Disabling CSRF protection is a bad idea.

Spring will automatically generate a new CSRF token after each request, and you need to include it in all HTTP requests with side-effects (PUT, POST, PATCH, DELETE).

In Postman you can use a test in each request to store the CSRF token in a global, e.g. when using CookieCsrfTokenRepository

pm.globals.set("xsrf-token", postman.getResponseCookie("XSRF-TOKEN").value);

And then include it as a header with key X-XSRF-TOKEN and value {{xsrf-token}}.

Upvotes: 4

Derrick
Derrick

Reputation: 4407

According to spring.io:

When should you use CSRF protection? Our recommendation is to use CSRF protection for any request that could be processed by a browser by normal users. If you are only creating a service that is used by non-browser clients, you will likely want to disable CSRF protection.

So to disable it:

@Configuration
public class RestSecurityConfig extends WebSecurityConfigurerAdapter {
  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable();
  }
}

Note: CSRF protection is enabled by default with Java Configuration

Upvotes: 82

kungyu
kungyu

Reputation: 15

I have solved it by adding the last attribute in my login page,maybe it will do yo a favor.

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"  isELIgnored="false"%>

Upvotes: -4

Related Questions