Spring security 401 Unauthorized even with permitAll
Asked Answered
A

7

8

I'm using Spring security to secure some endpoints in my REST service.

here's the security configuration class:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, jsr250Enabled = true, prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    // Other methods

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .cors()
                .and()
                .csrf()
                .disable()
                .exceptionHandling()
                .authenticationEntryPoint(this.jwtAuthenticationEntryPoint)
                .and()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests()
                .antMatchers("/",
                        "/favicon.ico",
                        "/**/*.png",
                        "/**/*.gif",
                        "/**/*.svg",
                        "/**/*.jpg",
                        "/**/*.html",
                        "/**/*.css",
                        "/**/*.js")
                .permitAll()
                .antMatchers(HttpMethod.POST, "/api/auth/**")
                .permitAll()
                .anyRequest()
                .authenticated();

        // Add our custom JWT security filter
        http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);

    }
}

As you can see i'm given the full access to /api/auth/signup and /api/auth/signin by using: .antMatchers(HttpMethod.POST, "/api/auth/**").permitAll()

for some reason when i tried those request in the postman, the "signup" request worked fine, but "signin" didn't works and gives me "401 Unauthorized"
i tried also .antMatchers("/**").permitAll()

here's my controller:

@RestController
public class UserController {

    private UserService userService;

    @Autowired
    public UserController(UserService userService) {
        this.userService = userService;
    }

    @PostMapping("/api/auth/signup")
    public ResponseEntity<RestResponse> registerUser(@Valid @RequestBody SignUpRequest signUpRequest,
                                                     UriComponentsBuilder uriComponentsBuilder)  {
        RestResponse restResponse = this.userService.register(signUpRequest);
        UriComponents uriComponents = uriComponentsBuilder.path("/users").buildAndExpand();
        return ResponseEntity.created(uriComponents.toUri()).body(restResponse);
    }

    @PostMapping("/api/auth/signin")
    public ResponseEntity<JwtAuthenticationResponse> authenticateUser(@Valid @RequestBody LoginRequest loginRequest) {
        return ResponseEntity.ok(this.userService.login(loginRequest));
    }
}
Adamina answered 20/10, 2018 at 9:30 Comment(5)
Can you try disabling the line .authenticationEntryPoint(this.jwtAuthenticationEntryPoint) ? Usually entry point methods also return 401 status.Reaganreagen
it gives me 403 forbiddenAdamina
Show your implementation of JwtAuthenticationFilter.Babylonian
@Ayoubk Your config looks ok - can you try with removing the HttpMethod.POST and make it antMatchers("/api/auth/**") just for testing purposes. Can you confirm you're sending the correct HTTP request types from Postman when invoking the REST endpoints?Arcane
Please add the signin request to the question.Calley
E
7

I had the same issue, not sure, but I think you need this order:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
            .authorizeRequests()
            .antMatchers(HttpMethod.POST, "/api/auth/**")
            .permitAll()
            .antMatchers("/",
                    "/favicon.ico",
                    "/**/*.png",
                    "/**/*.gif",
                    "/**/*.svg",
                    "/**/*.jpg",
                    "/**/*.html",
                    "/**/*.css",
                    "/**/*.js")
            .permitAll()                   
            .anyRequest()
            .authenticated()
            .and()
            .cors()
            .and()
            .exceptionHandling()
            .authenticationEntryPoint(this.jwtAuthenticationEntryPoint)
            .and()
            .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .csrf()
            .disable();

    // Add our custom JWT security filter
    http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);

}
Entellus answered 24/10, 2018 at 11:28 Comment(2)
What is the issue in mine: http.authorizeRequests().antMatchers(HttpMethod.GET, "/get/**").permitAll(); I am still getting Unauthorized error.Taffeta
I tried exactly as you pointed above and nothing, still giving the 401 status code.Fons
T
1

Your configuration is not working due to order in which the antMatcher is evaluated

 .and()
 .authorizeRequests()
 .antMatchers("/",
    "/favicon.ico",
    "/**/*.png",
    "/**/*.gif",
    "/**/*.svg",
    "/**/*.jpg",
    "/**/*.html",
    "/**/*.css",
    "/**/*.js")
 .permitAll()
 .antMatchers(HttpMethod.POST, "/api/auth/**")
 .permitAll()
 .anyRequest()
 .authenticated();

The order of the request match rule matters and more specific rules should go first. There is some conflict between both antMatcher rules and therefore the second rule i.e .antMatchers(HttpMethod.POST, "/api/auth/")** is ignored.

Therefore the order should be following :-

 .antMatchers(HttpMethod.POST, "/api/auth/**")
 .permitAll()
 .antMatchers("/",
    "/favicon.ico",
    "/**/*.png",
    "/**/*.gif",
    "/**/*.svg",
    "/**/*.jpg",
    "/**/*.html",
    "/**/*.css",
    "/**/*.js")
 .permitAll()
Tactful answered 27/10, 2018 at 11:38 Comment(0)
B
0

The last time i did it i remember the order is important.

@Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .cors()
                .and()
                .csrf()
                .disable()
                .exceptionHandling()
                .authenticationEntryPoint(this.jwtAuthenticationEntryPoint)
                .and()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests()
                .antMatchers(HttpMethod.POST, "/api/auth/**")
                .permitAll()
                .antMatchers("/",
                        "/favicon.ico",
                        "/**/*.png",
                        "/**/*.gif",
                        "/**/*.svg",
                        "/**/*.jpg",
                        "/**/*.html",
                        "/**/*.css",
                        "/**/*.js")
                .permitAll()                   
                .anyRequest()
                .authenticated();

        // Add our custom JWT security filter
        http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);

    }
Buckingham answered 24/10, 2018 at 3:16 Comment(0)
P
0

You need to add the following to your configure method /error is the default fall back when error occurs to the application due to any exception and it is secured by default.

    protected void configure(HttpSecurity httpSecurity) throws Exception {
    //disable CRSF
    httpSecurity
            //no authentication needed for these context paths
            .authorizeRequests()
            .antMatchers("/error").permitAll()
            .antMatchers("/error/**").permitAll()
            .antMatchers("/your Urls that dosen't need security/**").permitAll()

Also the below code snippet

 @Override
 public void configure(WebSecurity webSecurity) throws Exception
   {
     webSecurity
    .ignoring()
        // All of Spring Security will ignore the requests
        .antMatchers("/error/**")
     }  

Now you will not get 401 and get 500 exception with details when an exception occurred for permitAll Urls

Perdure answered 28/4, 2020 at 21:59 Comment(0)
V
0

I was having the same problem and it was due to the fact that I wasn´t using the default jdbc schema, so I was passing the queries needed by the default UserDetailsService, and my authorities table was empty, so it was not getting results searching by the username.

Valency answered 24/2, 2021 at 0:23 Comment(0)
E
0

I had the same error but my fault is to try login with the email and pass credentials. But my userdetailsservice loaduser by name not by email. After changing like below it worked successfully

public class UserDetailsImplServices implements UserDetailsService {

    @Autowired
    private UserRepository UserRepository;

    @Override
    public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
        //edit here to findbyemail not byname 
        UserModel user=UserRepository.findByEmail(email).get();
        return UserDetailsImpl.build(user);
    }
    
} 
Elaelaborate answered 21/6, 2022 at 15:30 Comment(0)
H
0

.anyRequest().authenticated() is preventing the permit all configuration. I tried to replace the .anyRequest() with antMatchers("/<context-path>/**"). It worked for me.

 protected void configure(HttpSecurity http) throws Exception {
        http
                .cors()
                .and()
                .csrf()
                .disable()
                .exceptionHandling()
                .authenticationEntryPoint(this.jwtAuthenticationEntryPoint)
                .and()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests()
                .antMatchers("/",
                        "/favicon.ico",
                        "/**/*.png",
                        "/**/*.gif",
                        "/**/*.svg",
                        "/**/*.jpg",
                        "/**/*.html",
                        "/**/*.css",
                        "/**/*.js")
                .permitAll()
                .antMatchers(HttpMethod.POST, "/api/auth/**")
                .permitAll()
                .antMatchers("/<context-path>/**")
                .authenticated();

        // Add our custom JWT security filter
        http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);

    }
Hera answered 10/9, 2022 at 7:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.