I've got a spring boot application that uses oauth2 for authentication. The oauth2 mechanism is working and clients can authenticate and receive their access tokens.
I want to secure the actuators endpoints with httpbasic authentication, i.e. not requiring the user to first use oauth2 for authentication and then access the actuator endpoints. What i've done so far is to set the following in properties file:
management.context-path=/admin/actuators
management.security.enabled=true
management.security.role=ADMIN
security.user.name=admin
security.user.password=password
I've tried various ways to set configuration with a ResourceServerConfigurerAdapter and WebSecurityConfigurerAdapter.
None of my attempts are working and it keeps on telling me
<oauth>
<error_description>
Full authentication is required to access this resource
</error_description>
<error>unauthorized</error>
</oauth>
What is the correct way to get OAUTH2 and the management endpoint to work?
The problem is that @EnableResourceServer
imports ResourceServerConfiguration
, which has an order of 3, far superior to ManagementServerProperties.ACCESS_OVERRIDE_ORDER
.
See Spring Boot documentation on actuator security and ordering config classes : http://docs.spring.io/spring-boot/docs/1.4.3.RELEASE/reference/htmlsingle/#boot-features-security-actuator
The default actuator security config is a lot more clever than just allowing access to the /health
endpoint and blocking the rest, it actually changes depending on management.port
and management.contextPath
, and it can get pretty hard to find the correct management endpoint URLs without leaving gaping holes in your security or messing with your own resources.
If you want to keep the benefit of the autoconfigured management security, two options :
This improvement has been suggested by @dsyer on the github thread :
@Component
@Slf4j
public class ResourceServerConfigurationPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof ResourceServerConfiguration) {
LOGGER.debug("Lowering order of ResourceServerConfiguration bean : {}", beanName);
ResourceServerConfiguration config = (ResourceServerConfiguration) bean;
config.setOrder(SecurityProperties.ACCESS_OVERRIDE_ORDER);
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
I just replaced my code below with this class, and it works perfectly.
If you don't like post processors for some reason, you can replace the @EnableResourceServer
with another configuration class whose order will come after the default management security :
/**
* Extend the default resource server config class, and downgrade its order
*/
public class ResourceServerLowPrecedenceConfiguration extends ResourceServerConfiguration {
/**
* This is enough to override Spring Boot's default resource security,
* but it does not takes over the management.
*/
@Override
public int getOrder() {
return SecurityProperties.ACCESS_OVERRIDE_ORDER;
}
}
And your own configuration class :
/** @EnableResourceServer is replaced by @Import using the low precedence config */
@Configuration
@Import(ResourceServerLowPrecedenceConfiguration.class)
public class YourOwnOAuth2Config extends ResourceServerConfigurerAdapter {
@Override
public void configure(final HttpSecurity http) throws Exception {
// Secure your resources using OAuth 2.0 here
}
}
EDIT : You can also rewrite your own @EnableResourceServer
annotation to shortcut the @Import
:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(ResourceServerLowPrecedenceConfiguration.class)
public @interface EnableResourceServer {
}
IMHO this should be the default behavior when spring-security-oauth is on the classpath.
See discussion on GitHub issue :
https://github.com/spring-projects/spring-boot/issues/5072
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With