Spring Security configuration: HTTP 403 error
Asked Answered
A

9

104

I'm trying to secure my website using Spring Security following the guides on the web.

So on my server side I have the following classes.

My WebSecurityConfigurerAdapter:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter implements ApplicationContextAware {

    @Override
    protected void registerAuthentication(AuthenticationManagerBuilde rauthManagerBuilder) throws Exception {
        authManagerBuilder.inMemoryAuthentication().withUser("user").password("password").roles("ADMIN");
    }
}

My controller:

@Controller
//@RequestMapping("/course")
public class CourseController implements ApplicationContextAware {

    @RequestMapping(value="/course", method = RequestMethod.GET, produces="application/json")
    public @ResponseBody List<Course> get(  // The criterion used to find.
        @RequestParam(value = "what", required = true) String what,
        @RequestParam(value = "value", required = true) String value) {
        //.....
    }

    @RequestMapping(value = "/course", method = RequestMethod.POST, produces = "application/json")
    public List<Course> upload(@RequestBody Course[] cs) {
        
    }
}

What confused me very much is the server does not respond to the POST/DELETE method, while the GET method works fine. BTW, I'm using RestTemplate on the client side.

Exceptions are:

Exception in thread "main" org.springframework.web.client.HttpClientErrorException: 403 Forbidden
    at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:91)
    at org.springframework.web.client.RestTemplate.handleResponseError(RestTemplate.java:574)
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:530)
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:487)
    at org.springframework.web.client.RestTemplate.delete(RestTemplate.java:385)
    at hello.Application.createRestTemplate(Application.java:149)
    at hello.Application.main(Application.java:99)

I've searched the internet for days. Still don't have a clue. Please help. Thanks so much

Ammonia answered 19/10, 2013 at 16:18 Comment(1)
is that correct? roles("ADMI N"). There is a space between 'I' and 'N'.Deakin
D
234

The issue is likely due to CSRF protection. If users will not be using your application in a web browser, then it is safe to disable CSRF protection. Otherwise you should ensure to include the CSRF token in the request.

To disable CSRF protection you can use the following:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig
    extends WebSecurityConfigurerAdapter implements ApplicationContextAware {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            // ...
            .csrf().disable();
    }

    @Override
    protected void registerAuthentication(AuthenticationManagerBuilder authManagerBuilder) throws Exception {
        authManagerBuilder
            .inMemoryAuthentication()
                .withUser("user").password("password").roles("ADMIN");
    }
}
Duplessismornay answered 21/10, 2013 at 13:48 Comment(4)
Thanks Rob. It is the csrf problem. Yes, I don't want my users to use web browser to using my application. It's working well on the client side. But on the server side I get this: o.s.web.servlet.PageNotFound : Request method 'POST' not supported Strange. should I ignore it?Ammonia
I think the PageNotFound is a separate issue that I would address. Likely you will need to post another question with more information regarding this error.Duplessismornay
Disabling the csrf security config has indeed solved my issue. I find it hard to keep up with all these hidden automatic features brought in by Spring starters.Borstal
Hi everyone, in my case, it was not about csrf. My proxy was forwarding the request to the backend as http instead of https. This also caused 403, and it was hard to track because also spring was refusing requests for POST and DELETE only (so requests that change state) I had to add the forward headers config to make it work.Rescind
R
8

The issue is likely due to CSRF protection, agree with the top comment. Nevertheless, by using this configuration, the method cancells the spring security.

So you can use the following code:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();

        auth
                .inMemoryAuthentication()
                    .withUser("admin")
                        .password(encoder.encode("admin"))
                        .roles("ADMIN", "USER")
                .and()
                    .withUser("user")
                        .password(encoder.encode("password"))
                        .roles("USER");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .anyRequest()
                .authenticated()
                .and()
                .httpBasic();

        http.csrf().disable();
    }
}
Rave answered 4/1, 2022 at 7:56 Comment(0)
H
5

The issue may be related to CSRF or CORS Security Protection.

  • FOR CSRF: You can disable it if the application users did not use it from browsers.
  • For CORS: You can specify the origin and allow HTTP Methods.

The below code disable CSRF and allow all origins and HTTP methods. so be aware when using it.

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter  implements WebMvcConfigurer {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();
    }

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**").allowedMethods("*");
    }

}
Hundredpercenter answered 30/8, 2020 at 23:16 Comment(2)
Is it dangerous in production to disable csrf()?Cambrai
Don't disable csrf. Its a huge security risk. if you don't know this i HIGHLY recommend that you go look up what it is before you disable it.Baptism
P
5

I had this problem after upgrading my service to Spring Boot 3. Automatic tests started to fail with a 403 status. After quite a lot of headaches, I found out it is caused by removing trailing slash from URL matching. The change is described here. So check that you are calling the correct URL.

Wrong:

/api/foo/

Right:

/api/foo
Photo answered 13/1, 2023 at 9:51 Comment(0)
A
2

I've been looking for days too! Simply disabling CSRF on your configure method with http.csrf().disable(); is all that needed to be done for my put requests to stop receiving 403.

Affinal answered 21/10, 2020 at 17:57 Comment(0)
M
1

I'm posting this in case someone else finds it useful in the future. I spent hours looking for what was failing and finally I find the solution, on Postman making a POST to http://localhost:8080/login/ is not the same as making a POST to http://localhost:8080/login (with "/" at the end of request it will return 403 forbidden)

Manpower answered 25/11, 2022 at 19:41 Comment(1)
Nah, this is not the case for me! I had to disable CSRFBlackness
D
0

Check your token which you are sending through 'Header' and also query in your database for the same token whether that token exist or not.

Note : The above is applicable only in case you are using Spring Boot token authentication mechanism.

Documentary answered 4/3, 2019 at 7:49 Comment(0)
C
0

At present, for Spring Security 6.1.3 the below configuration is sufficient for basic authentication

   @Bean
   public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity)throws Exception {
  httpSecurity.httpBasic(Customizer.withDefaults());
  return httpSecurity.build(); }
Cozza answered 2/9, 2023 at 17:3 Comment(0)
G
-5
http.httpBasic().disable();
http.authorizeRequests().antMatchers("/signup").permitAll().antMatchers("/*")
     .fullyAuthenticated().and().formLogin()
     .and().csrf().disable();
http.csrf().disable();
Garnett answered 12/4, 2021 at 18:55 Comment(3)
Code only answers are discouragedSimonetta
Please explain your answerEstaminet
Why there is multiple .csrf().disable() ?Malatya

© 2022 - 2024 — McMap. All rights reserved.