Spring/Springboot OAuth2 - Integrate custom ClientDetailsUserDetailsService - spring

I have successfully configured my application to support both Basic, form-based and OAuth2 authentication, but ran into a bit of a snag trying to customize the ClientDetailsUserDetailsService in OAuth. The behavior I'm noticing is that the Spring OAuth ClientDetailsUserDetailsService is always being used despite my attempts to inject a new custom implementation.
The reason I want to customize this class is to return a custom User Details object similar to what I use for the Basic Auth and Form authentication.
I've read multiple posts on the site related to this same topic, but was not able to resolve the issue with the suggested approaches (ie: Previous post)
Spring's AuthorizationServerSecurityConfigurer class seems to always use the ClientDetailsUserDetailsService regardless of what you inject.
Thing(s) I've tried:
Create an #Bean referencing my custom user details impl and set the custom user details in the AuthorizationServerEndpointsConfigurer.userDetailsService.
Set the user details in the GlobalAuthenticationConfigurerAdapter
#Configuration
#Order(Ordered.HIGHEST_PRECEDENCE)
public class AuthenticationManagerConfiguration
extends GlobalAuthenticationConfigurerAdapter {
#Autowired
private UserDetailsService userService;
#Override
public void init(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(clientDetailsUserDetailsService());// Inject custom
}
}
Created a custom WebSecurityConfigurerAdapter and set the user details service in the HttpSecurity object ie:
#Override
public void configure(HttpSecurity http) throws Exception {
http
.requestMatchers().antMatchers("/oauth/**")
.requestMatchers().antMatchers("/api-token/**")
.authorizeRequests()
.anyRequest().authenticated();
http.userDetailsService(clientDetailsUserService());
http.authenticationProvider(oauthDaoAuthenticationProvider(encryptionService));
}
Create a new DaoAuthenticationProvider Bean and manually set my custom user details service for oauth requests.
Any advice or help is greatly appreciated and again, I do have OAuth working, but would like to tweak the implementation a bit without having to hack into the Spring classes to achieve it. Thanks!

Related

Combining OAuth2 with http basic authentication spring security

I've implemented OAuth2 using spring boot and spring security. Now I've different set of APIs available and I want to use different authentication methods for it. For e.g I want to use OAuth2 for /users/** apis and Http Basic Authentication for /admin/** APIs.
However, OAuth2 shouldn't work for /admin/** and HTTP basic shouldn't work for /users/** APIs.
Any help would be great!
In Spring Security you can have multiple filter chains that handle different requests.
So you can have one that handles requests to the /users/** uri which will have the Basic Authentication filter , and one that handles requests to /admin/** uri which will have the Oauth2 filters. To set this up, you need 2 instances of the WebSecurityConfigurerAdapter
One for Oauth2
#Configuration
#Order(1)
public static class Oauth2ConfigurationAdapter extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http.mvcMatcher("/user/**")
......
And another for Basic:
#Configuration
#Order(2)
public static class BasicConfigurationAdapter extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http.mvcMatcher("/admin/**")
......
This article explains it in more detail: https://www.baeldung.com/spring-security-multiple-entry-points
Also this code does something similar with Digest auth for /admin and Basic for all other. https://github.com/wlesniak/spring-security-authn-authz-course/tree/master/module_2/mod2_crypto_portfolio_digest

SAML and Oauth2 in a single spring boot application

In an attempt to develop a generic identity service for a project I am working on, I need to support Azure ADFS-based SAML security for UI pages and Oauth2 based security for my REST APIs in a single spring-boot application
I have a spring boot application attempting to provide SAML based protection for some of my UI resources and Oauth2 based protection for my REST APIs. The UI pages and the REST APIs are hosted in the same spring boot based application. I have a SecurityConfiguration class that extends WebSecurityConfigurerAdapter and that contains my SAML configuration. I also have a ResourceServerConfig class that extends ResourceServerConfigurerAdapter where I have tried to configure the Oauth2 authentication for my REST APIs.
Here is what my code looks like
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter
{
/////// Other methods //////
#Override
protected void configure(HttpSecurity http) throws Exception
{
http.authorizeRequests().anyRequest().authenticated();
http.httpBasic().authenticationEntryPoint(samlEntryPoint());
http.csrf().disable();
http.addFilterBefore(metadataGeneratorFilter(), ChannelProcessingFilter.class).addFilterAfter(samlFilter(), BasicAuthenticationFilter.class);
http.authorizeRequests().antMatchers("/oauth/token").permitAll().anyRequest().authenticated();
}
The ResourceServerConfig class looks something like the following
#Configuration
#EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter
{
#Override
public void configure(HttpSecurity http) throws Exception
{
http
.csrf().disable()
.anonymous().and()
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS).permitAll()
.antMatchers("/api/**").authenticated();
}
My problem is, with the above configuration in place, I can either get SAML protection on my UI pages OR Oauth2 protection on my APIs but not both. If I remove #EnableResourceServer from the ResourceServerConfig class and try to access one of my UI pages, I am reliably redirected to the microsoft Azure login page which redirects me back to my UI page after successful authentication. But with this, any attempt to access my apis (with valid bearer tokens) results in a redirection to the microsoft Azure login page. If I re-enable #EnableResourceServer my APIs get protected and behave as expected but SAML protection for all UI pages gets completely disabled with spring allowing unhindered access to all UI resources.
I can't figure out how to tell spring boot to use which authentication framework for the two kinds of URL patterns I have. Is such a thing even possible?
Any help with this would be appreciated.
Regards,
Dipak Jha
I think I have found an answer to my own question. This reply here provides a workable solution. A properly configured OAuthRequestedMatcher seems to do the trick. Please let me know if someone thinks this can be done in a better way.
Regards
Dipak Jha

How to manually change the Authentication Provider in Spring Security

The authentication provider is set in
#Override
public void configure(AuthenticationManagerBuilder auth) {
auth.authenticationProvider(authenticationProvider);
}
Is it possible to change the Authentication Provider during runtime in SpringBoot?
Instance of configured AuthenticationManager eventually will be passed to one of the implementations of org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter. This base filter class has setter for AuthenticationManager so yes, essentially you can replace AuthenticationManager in runtime provided that you have access to the configured authentication filter.
But I doubt that it would be a good idea because you can have several authentication filters where AuthenticationManager should be replaced too. Also Spring does not expect this behavior so finally it can lead to inconsistency in the configuration.
Depending on your needs I would suggest to provide custom implementation of AuthenticationManager that changes its logic accordingly to some conditions.

Spring Boot 2 http.httpBasic().disable(); not working

I recently upgraded from Spring Boot 1.x to Spring Boot 2.0.3 and I am trying to disable basic auth with no success.
#Configuration
#EnableWebSecurity(debug=true)
#EnableGlobalMethodSecurity(securedEnabled = true)
public class CustomSecurity extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.httpBasic().disable();
// the rest of my config
}
}
What hidden gem am I missing to just simply turn off basic auth?
Why does turning things off in Spring need to be so difficult now?
I was reading this:
https://github.com/spring-projects/spring-boot/issues/10306
and I have to agree that it should be much easier and a clearer explanation should be provided on how to turn this off.
EDIT
This link https://spring.io/blog/2017/09/15/security-changes-in-spring-boot-2-0-m4 talks about how the property was removed but doesn't say anything about how to continue to use the configuration as it exists in current application that utilize it.

Dynamic Spring Security update

I faced issue trying to get my roles updated from DB. Is it possible to programmatically add configuration to spring security. e.g.
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN");
Can i add a new configuration say .antMatchers("/user-service/**").hasRole("USER_DRIVER"); programmatically?
I tried adding a scheduled job using spring boot to refresh the configuration. However, they are not accepted.
Help appreciated.
Many thanks.

Resources