I have detected a behaviour I find confusing, it might be intended, but I could not determine if so.
The DaoAuthenticationprovider does not get created when I use Basic Auth together with specific oauth2 configuration. Without this specific configuration inside of application.yaml everything works. Is it included, I get an internal exception resulting in a 401. I described both cases below.
My question would be: If this is correct behaviour, how do I get a default Basic Auth running without providing a custom AuthenticationProvider etc.? I did not try to achieve this myself, because I do not know how to easily achieve it, and also, I'd rather use default behaviour if possible.
Basic Authentication does not work when
curl --location --request GET 'http://localhost:8080/actuator/info' --header 'Authorization: Basic dXNlcjpwYXNzd29yZA=='
the response is
{"timestamp":"2021-05-25T13:25:30.198+00:00","status":401,"error":"Unauthorized","message":"","path":"/actuator/info"}
inside Spring I get a ProviderNotFoundException:
/actuator/info at position 5 of 11 in additional filter chain; firing Filter: 'BasicAuthenticationFilter'
2021-05-25 15:23:32.727 DEBUG 4216 --- [nio-8080-exec-2] o.s.s.w.a.www.BasicAuthenticationFilter : Basic Authentication Authorization header found for user 'user'
2021-05-25 15:23:32.730 DEBUG 4216 --- [nio-8080-exec-2] o.s.s.w.a.www.BasicAuthenticationFilter : Authentication request for failed!
org.springframework.security.authentication.ProviderNotFoundException: No AuthenticationProvider found for org.springframework.security.authentication.UsernamePasswordAuthenticationToken
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:251) ~[spring-security-core-5.3.4.RELEASE.jar:5.3.4.RELEASE]
when debugging I found out that DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); is not called when InitializeUserDetailsBeanManagerConfigurer.java gets configured. Actually it seems InitializeUserDetailsBeanManagerConfigurer is not really called for configuration, I landed instead here GlobalAuthenticationConfigurerAdapter.java.
To make everything work
I only need to remove the following lines from application.yaml:
oauth2:
resourceserver:
jwt:
issuer-uri: https://someissuer
jwk-set-uri: https://somejwkuri
then I get a 200 from the same curl and this inside spring:
/actuator/info at position 5 of 11 in additional filter chain; firing Filter: 'BasicAuthenticationFilter'
2021-05-25 15:51:21.845 DEBUG 16540 --- [nio-8080-exec-1] o.s.s.w.a.www.BasicAuthenticationFilter : Basic Authentication Authorization header found for user 'user'
2021-05-25 15:51:21.845 DEBUG 16540 --- [nio-8080-exec-1] o.s.s.authentication.ProviderManager : Authentication attempt using org.springframework.security.authentication.dao.DaoAuthenticationProvider
2021-05-25 15:51:22.036 DEBUG 16540 --- [nio-8080-exec-1] o.s.s.w.a.www.BasicAuthenticationFilter : Authentication success: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@ed8ad585: Principal: org.springframework.security.core.userdetails.User@36ebcb: Username: user; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ENDPOINT_ADMIN; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ENDPOINT_ADMIN
Code
application.yaml
There is other configuration like flyway, hikari, camunda, but all of these are separate, and do not affect the behaviour I observed.
spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: https://someissuer
jwk-set-uri: https://somejwkuri
user:
name: user
password: password
roles: ENDPOINT_ADMIN
server:
port: 8080
management:
endpoints:
web:
exposure:
include: health,info,metrics,prometheus,loggers
cors:
allowed-origins: "*"
allowed-methods: GET,POST
security:
enabled: false
logging:
level:
org:
springframework: DEBUG
pattern:
console:%d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} - %msg%n
WebSecurityConfigurerAdapter extending class
Its an inner class, because I make use of multiple filter chains, but I excluded the others during test - no impact
public class SecurityConfig {
@Order(1)
@Configuration
public static class BasicAuthSecurityConfig extends WebSecurityConfigurerAdapter {
// info is excluded on purpose
private final String[] ENDPOINTS = { "health", "metrics", "prometheus", /* "info" */ };
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().requestMatcher(EndpointRequest.toAnyEndpoint()).authorizeRequests()
.requestMatchers(EndpointRequest.to(ENDPOINTS)).permitAll()
.requestMatchers(EndpointRequest.toAnyEndpoint()).hasRole("ENDPOINT_ADMIN").and()
.httpBasic();
}
}
// other commented out inner classes for oauth and general handling
}
build.gradle
Very short version, but it should illustrate on what this is built.
plugins {
//Spring Boot
id 'org.springframework.boot' version '2.3.3.RELEASE'
}
dependencies {
compile 'org.springframework.boot:spring-boot-starter-security'
compile 'org.springframework.boot:spring-boot-starter-actuator'
compile 'org.springframework.boot:spring-boot-starter-amqp'
compile 'org.springframework.boot:spring-boot-starter-data-jpa'
compile 'org.springframework.boot:spring-boot-starter-data-rest'
compile 'org.springframework.boot:spring-boot-starter-web'
compile 'org.springframework.cloud:spring-cloud-starter-kubernetes-config'
compile 'org.springframework.cloud:spring-cloud-starter-openfeign'
compile 'org.springframework.security:spring-security-oauth2-resource-server'
compile 'org.springframework.security:spring-security-oauth2-jose'
compile 'org.springframework.security:spring-security-config'
}