0

I've got a very weird problem with Spring Security and basic auth. I'd basically like to protect swagger ui with basic auth. Everything works (without auth) until I introduce the following in spring config:

<http pattern="/swagger*/**" xmlns="http://www.springframework.org/schema/security"
          authentication-manager-ref="basicAuthenticationManager">
        <http-basic />
        <intercept-url pattern="/swagger*/**" access="isAuthenticated()" />
</http>

This results in a 404 due to a permission denied, the log shows:

DEBUG [HTTP38] [ExceptionTranslationFilter] Chain processed normally
DEBUG [HTTP22] [AntPathRequestMatcher] Checking match of request : '/swagger-ui.html'; against '/swagger*/**'
DEBUG [HTTP22] [FilterChainProxy] /swagger-ui.html at position 1 of 11 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
DEBUG [HTTP22] [HttpSessionSecurityContextRepository] No HttpSession currently exists
DEBUG [HTTP22] [HttpSessionSecurityContextRepository] No SecurityContext was available from the HttpSession: null. A new one will be created.
DEBUG [HTTP22] [FilterChainProxy] /swagger-ui.html at position 2 of 11 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
DEBUG [HTTP22] [FilterChainProxy] /swagger-ui.html at position 3 of 11 in additional filter chain; firing Filter: 'HeaderWriterFilter'
DEBUG [HTTP22] [FilterChainProxy] /swagger-ui.html at position 4 of 11 in additional filter chain; firing Filter: 'CsrfFilter'
DEBUG [HTTP22] [FilterChainProxy] /swagger-ui.html at position 5 of 11 in additional filter chain; firing Filter: 'BasicAuthenticationFilter'
DEBUG [HTTP22] [FilterChainProxy] /swagger-ui.html at position 6 of 11 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
DEBUG [HTTP22] [HttpSessionRequestCache] saved request doesn't match
DEBUG [HTTP22] [FilterChainProxy] /swagger-ui.html at position 7 of 11 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
DEBUG [HTTP22] [FilterChainProxy] /swagger-ui.html at position 8 of 11 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
DEBUG [HTTP22] [AnonymousAuthenticationFilter] Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken@4f862d10: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS'
DEBUG [HTTP22] [FilterChainProxy] /swagger-ui.html at position 9 of 11 in additional filter chain; firing Filter: 'SessionManagementFilter'
DEBUG [HTTP22] [FilterChainProxy] /swagger-ui.html at position 10 of 11 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
DEBUG [HTTP22] [FilterChainProxy] /swagger-ui.html at position 11 of 11 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
DEBUG [HTTP22] [AntPathRequestMatcher] Checking match of request : '/swagger-ui.html'; against '/swagger*/**'
DEBUG [HTTP22] [FilterSecurityInterceptor] Secure object: FilterInvocation: URL: /swagger-ui.html; Attributes: [isAuthenticated()]
DEBUG [HTTP22] [FilterSecurityInterceptor] Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@4f862d10: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS
DEBUG [HTTP22] [AffirmativeBased] Voter: org.springframework.security.web.access.expression.WebExpressionVoter@10de9715, returned: -1
DEBUG [HTTP22] [ExceptionTranslationFilter] Access is denied (user is anonymous); redirecting to authentication entry point
org.springframework.security.access.AccessDeniedException: Access is denied
    at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:84) ~[spring-security-core-5.1.4.RELEASE.jar:5.1.4.RELEASE]
    at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:233) ~[spring-security-core-5.1.4.RELEASE.jar:5.1.4.RELEASE]
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:124) ~[spring-security-web-5.1.4.RELEASE.jar:5.1.4.RELEASE]
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91) ~[spring-security-web-5.1.4.RELEASE.jar:5.1.4.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.1.4.RELEASE.jar:5.1.4.RELEASE]
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:119) [spring-security-web-5.1.4.RELEASE.jar:5.1.4.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.4.RELEASE.jar:5.1.4.RELEASE]

So it seems the AnonymousAuthFilter sets anonymous which is not allowed due to the access="isAuthenticated()".

So if I add the following:

    <http pattern="/swagger*/**" xmlns="http://www.springframework.org/schema/security"
          authentication-manager-ref="basicAuthenticationManager">
        <http-basic />
        <intercept-url pattern="/swagger*/**" access="isAuthenticated()" />
        <anonymous enabled="false" />
    </http>

It will complain about missing auth object (An Authentication object was not found in the SecurityContext):

DEBUG [HTTP15] [ExceptionTranslationFilter] Chain processed normally
DEBUG [HTTP25] [AntPathRequestMatcher] Checking match of request : '/swagger-ui.html'; against '/swagger*/**'
DEBUG [HTTP25] [FilterChainProxy] /swagger-ui.html at position 1 of 10 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
DEBUG [HTTP25] [HttpSessionSecurityContextRepository] No HttpSession currently exists
DEBUG [HTTP25] [HttpSessionSecurityContextRepository] No SecurityContext was available from the HttpSession: null. A new one will be created.
DEBUG [HTTP25] [FilterChainProxy] /swagger-ui.html at position 2 of 10 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
DEBUG [HTTP25] [FilterChainProxy] /swagger-ui.html at position 3 of 10 in additional filter chain; firing Filter: 'HeaderWriterFilter'
DEBUG [HTTP25] [FilterChainProxy] /swagger-ui.html at position 4 of 10 in additional filter chain; firing Filter: 'CsrfFilter'
DEBUG [HTTP25] [FilterChainProxy] /swagger-ui.html at position 5 of 10 in additional filter chain; firing Filter: 'BasicAuthenticationFilter'
DEBUG [HTTP25] [FilterChainProxy] /swagger-ui.html at position 6 of 10 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
DEBUG [HTTP25] [HttpSessionRequestCache] saved request doesn't match
DEBUG [HTTP25] [FilterChainProxy] /swagger-ui.html at position 7 of 10 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
DEBUG [HTTP25] [FilterChainProxy] /swagger-ui.html at position 8 of 10 in additional filter chain; firing Filter: 'SessionManagementFilter'
DEBUG [HTTP25] [FilterChainProxy] /swagger-ui.html at position 9 of 10 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
DEBUG [HTTP25] [FilterChainProxy] /swagger-ui.html at position 10 of 10 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
DEBUG [HTTP25] [AntPathRequestMatcher] Checking match of request : '/swagger-ui.html'; against '/swagger*/**'
DEBUG [HTTP25] [FilterSecurityInterceptor] Secure object: FilterInvocation: URL: /swagger-ui.html; Attributes: [isAuthenticated()]
DEBUG [HTTP25] [ExceptionTranslationFilter] Authentication exception occurred; redirecting to authentication entry point
org.springframework.security.authentication.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext
    at org.springframework.security.access.intercept.AbstractSecurityInterceptor.credentialsNotFound(AbstractSecurityInterceptor.java:379) ~[spring-security-core-5.1.4.RELEASE.jar:5.1.4.RELEASE]
    at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:223) ~[spring-security-core-5.1.4.RELEASE.jar:5.1.4.RELEASE]
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:124) ~[spring-security-web-5.1.4.RELEASE.jar:5.1.4.RELEASE]
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91) ~[spring-security-web-5.1.4.RELEASE.jar:5.1.4.RELEASE]
    ....

I'd like to point out:

  1. This is a big enterprise application and there is stuff around it. Web contexts, however, are pretty narrowed down and I really removed almost everything else.
  2. This used to work. What I changed was the mapping in web.xml. Before it was /v2/* that was mapped to springmvc-servlet, now it is /*.

Any ideas? To me it seems correct and it all looks good in log too - it just never asks for basic auth.

Any input welcome.

Thank you and BR

Dario

Dario Pedol
  • 2,070
  • 14
  • 24
  • About the second configuration, you are getting what it is expected, you do not have add an AnonymousAuthentication, therefore your security context is empty. For my the question is why your BasicAuthenticationFilter is not working, can you show us an example of your calls to the endpoints ?? are the calls containing actually the username:password ?? – Juan BC Dec 23 '20 at 14:58
  • I just open the localhost/swagger-ui.html in the browser and would expect it to open the dialog, asking for basic auth credentials. – Dario Pedol Dec 23 '20 at 15:13
  • Very interesting. It works using Postman, when I provide the credentials manually. How does the Browser decide to show that dialog? – Dario Pedol Dec 23 '20 at 16:09
  • I think I'm figuring it out. The entry point might not be correct. https://stackoverflow.com/questions/37763186/spring-boot-security-shows-http-basic-auth-popup-after-failed-login – Dario Pedol Dec 23 '20 at 16:14
  • I figured it out. It was error page redirects in web.xml, preventing the dialog from showing. – Dario Pedol Dec 23 '20 at 16:45

0 Answers0