Spring Security permitAll not allowing anonymous access
Asked Answered
Z

8

83

I have a single method that I want to allow both anonymous and authenticated access to.

I am using Spring Security 3.2.4 with Java based configuration.

The overridden configure method (in my custom configuration class extending WebSecurityConfigurerAdapter) has the following http block:

    http
        .addFilterBefore(muiltpartFilter, ChannelProcessingFilter.class)
        .addFilterBefore(cf, ChannelProcessingFilter.class)
        .authorizeRequests()
            .anyRequest()
            .authenticated()
            .and()
        .authorizeRequests()
            .antMatchers("/ping**")
            .permitAll()
            .and()
        .formLogin()
            .loginPage("/login")
            .permitAll()
            .and()
        .logout()
            .logoutUrl("/logout")
        .logoutSuccessUrl("/login");

The ping request handler and method is in a controller that also contains the login handler, and it has no separate @PreAuthorize or other annotations that might cause the issue.

The problem is that anonymous access is denied and the user is redirected to the login page.

Logging at the debug level, I see the following feedback from Spring Security:

[2014-07-11 13:18:04,483] [DEBUG] [org.springframework.security.web.access.intercept.FilterSecurityInterceptor] Secure object: FilterInvocation: URL: /ping; Attributes: [authenticated]
[2014-07-11 13:18:04,483] [DEBUG] [org.springframework.security.web.access.intercept.FilterSecurityInterceptor] Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@6faad796: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@ffffa64e: RemoteIpAddress: 192.168.2.128; SessionId: 0EF6B13BBA5F00C020FF9C35A6E3FBA9; Granted Authorities: ROLE_ANONYMOUS
[2014-07-11 13:18:04,483] [DEBUG] [org.springframework.security.access.vote.AffirmativeBased] Voter: org.springframework.security.web.access.expression.WebExpressionVoter@123f2882, returned: -1
[2014-07-11 13:18:04,483] [DEBUG] [org.springframework.security.web.access.ExceptionTranslationFilter] Access is denied (user is anonymous); redirecting to authentication entry point

What I'm trying to accomplish is to have a method that can be called at any point and which will send a reply indicating whether or not the request is inside a logged-in session.

Zebec answered 11/7, 2014 at 11:31 Comment(4)
What happens if you use "/ping" or "/ping*" as the pattern?Classieclassification
Are you the Luke Taylor, whose name I've seen many many times in Spring Security Javadoc comments? Quite an honor if so! The behavior is the same using /ping and using /ping*, unfortunately.Zebec
Shouldn't your authorizeRequests().anyRequest().authenticated() be the last one? In XML the ordering of the elements is important so I can imagine the same applies to java config.Playwriting
@M.Deinum, I tried your suggestion by placing the .authorizeRequests().antMatchers("/ping**").permitAll() before, and it now works. Thanks!Zebec
H
65

The permission order is important, it works when I configure it like this:

.authorizeRequests()
        .antMatchers("/ping**")
        .permitAll()
        .and()
.authorizeRequests()
        .anyRequest()
        .authenticated()
        .and()
Hortative answered 3/8, 2015 at 16:15 Comment(0)
I
47

I saw the same issue. Make sure you didn't call
super.configure(http);
anyRequest().authenticated();
is called by default.

Ilianailine answered 17/7, 2014 at 0:24 Comment(0)
C
19

Need to add .anonymous()

http
    .addFilterBefore(muiltpartFilter, ChannelProcessingFilter.class)
    .addFilterBefore(cf, ChannelProcessingFilter.class)
    .anonymous().and()
    .authorizeRequests().anyRequest().authenticated().and()
        .authorizeRequests()
            .antMatchers("/ping**")
            .permitAll()
            .and()
        .formLogin()
            .loginPage("/login")
            .permitAll()
            .and()
        .logout()
            .logoutUrl("/logout")
        .logoutSuccessUrl("/login");

Referred from: https://mcmap.net/q/244196/-spring-security-get-user-info-in-rest-service-for-authenticated-and-not-authenticated-users

Calhoun answered 14/12, 2017 at 1:41 Comment(2)
Oh how I wanted this to work. I am getting : nested exception is java.lang.IllegalStateException: Can't configure antMatchers after anyRequest. springBootVersion = '2.3.3.RELEASE'Arequipa
FWIW, I had to put .anonymous() at the end of the filter chain to get things to work right. It appears that the behavior of .anonymous is to add an "anonymous" user, so if you put it earlier in the filter chain it adds that as the user and calls it good.Halfback
H
5

I was struggling with this a problem for a day. What I had to do in the end is to remove the @Component annotation from my filter, and instantiate it manually, as described in this answer.

So for the original question this would look something like:

http
    .addFilterBefore(new MultiPartFilter(), ChannelProcessingFilter.class)
    .addFilterBefore(new OtherFilter(), ChannelProcessingFilter.class)
    .authorizeRequests() // ... rest omitted for brevity

I also had to remove these endpoints from spring security altogether by overriding configure(WebSecurity web) as described in J. Perez's answer:

@Override
public void configure(WebSecurity web) throws Exception {
    web.ignoring().antMatchers("/ping**");
}
Hairless answered 13/2, 2021 at 11:35 Comment(0)
R
5

I wasn't able to POST to a permitAll() url. After that, I found that the reason is due to CSRF enabled. SO I disable it by:

http.....and().csrf().disable();

P.S: it's not a good idea to disable it, I will have to figure out how to POST with CSRF in the future.

Rump answered 31/10, 2022 at 23:12 Comment(0)
R
2
@Override
public void configure(HttpSecurity http) throws Exception {
    http.anonymous().and()...;
}

@Override
public void configure(WebSecurity web) throws Exception {
    web.ignoring().mvcMatchers("/ping**");
}
Relieve answered 16/6, 2020 at 0:12 Comment(0)
D
0

This occurred to me due to that I'm setting the blank token API request, I had to remove this from my angular

if (token) {
    newHeaders = newHeaders.append('Authorization', 'Bearer' + ' ' + token);
}

Here the token is empty

Durbin answered 16/3, 2022 at 13:7 Comment(0)
B
0

Make sure the class is annotated with @Configuration. 🤦‍♀️

Benefield answered 19/5, 2022 at 15:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.