Add custom UserDetailsService to Spring Security OAuth2 app

Add custom UserDetailsService to Spring Security OAuth2 app

spring security oauth2 custom authentication provider
spring boot security custom authentication
spring boot rest oauth2 example
spring security userdetailsservice
spring security userdetailsservice not called
spring security custom authorization
spring security-oauth2 xml configuration example
spring boot oauth2 client credentials example

How do I add the custom UserDetailsService below to this Spring OAuth2 sample?

The default user with default password is defined in the application.properties file of the authserver app.

However, I would like to add the following custom UserDetailsService to the demo package of the authserver app for testing purposes:

package demo;

import java.util.List;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.provisioning.UserDetailsManager;
import org.springframework.stereotype.Service;

@Service
class Users implements UserDetailsManager {

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        String password;
        List<GrantedAuthority> auth = AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER");
        if (username.equals("Samwise")) {
            auth = AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_HOBBIT");
            password = "TheShire";
        }
        else if (username.equals("Frodo")){
            auth = AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_HOBBIT");
            password = "MyRing";
        }
        else{throw new UsernameNotFoundException("Username was not found. ");}
        return new org.springframework.security.core.userdetails.User(username, password, auth);
    }

    @Override
    public void createUser(UserDetails user) {// TODO Auto-generated method stub
    }

    @Override
    public void updateUser(UserDetails user) {// TODO Auto-generated method stub
    }

    @Override
    public void deleteUser(String username) {// TODO Auto-generated method stub
    }

    @Override
    public void changePassword(String oldPassword, String newPassword) {
        // TODO Auto-generated method stub
    }

    @Override
    public boolean userExists(String username) {
        // TODO Auto-generated method stub
        return false;
    }
}

As you can see, this UserDetailsService is not autowired yet, and it purposely uses insecure passwords because it is only designed for testing purposes.

What specific changes need to be made to the GitHub sample app so that a user can login as username=Samwise with password=TheShire, or as username=Frodo with password=MyRing? Do changes need to be made to AuthserverApplication.java or elsewhere?


SUGGESTIONS:


The Spring OAuth2 Developer Guide says to use a GlobalAuthenticationManagerConfigurer to configure a UserDetailsService globally. However, googling those names produces less than helpful results.

Also, a different app that uses internal spring security INSTEAD OF OAuth uses the following syntax to hook up the UserDetailsService, but I am not sure how to adjust its syntax to the current OP:

@Order(Ordered.HIGHEST_PRECEDENCE)
@Configuration
protected static class AuthenticationSecurity extends GlobalAuthenticationConfigurerAdapter {

    @Autowired
    private Users users;

    @Override
    public void init(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(users);
    }
}

I tried using @Autowire inside the OAuth2AuthorizationConfig to connect Users to the AuthorizationServerEndpointsConfigurer as follows:

@Autowired//THIS IS A TEST
private Users users;//THIS IS A TEST

@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
   endpoints.authenticationManager(authenticationManager)
        .accessTokenConverter(jwtAccessTokenConverter())
        .userDetailsService(users)//DetailsService)//THIS LINE IS A TEST
        ;
}

But the Spring Boot logs indicate that the user Samwise was not found, which means that the UserDetailsService was not successfully hooked up. Here is the relevant excerpt from the Spring Boot logs:

2016-04-20 15:34:39.998 DEBUG 5535 --- [nio-9999-exec-9] o.s.s.a.dao.DaoAuthenticationProvider    :  
        User 'Samwise' not found
2016-04-20 15:34:39.998 DEBUG 5535 --- [nio-9999-exec-9]   
        w.a.UsernamePasswordAuthenticationFilter :  
        Authentication request failed:  
        org.springframework.security.authentication.BadCredentialsException:  
        Bad credentials

What else can I try?


I ran into a similar issue when developing my oauth server with Spring Security. My situation was slightly different, as I wanted to add a UserDetailsService to authenticate refresh tokens, but I think my solution will help you as well.

Like you, I first tried specifying the UserDetailsService using the AuthorizationServerEndpointsConfigurer, but this does not work. I'm not sure if this is a bug or by design, but the UserDetailsService needs to be set in the AuthenticationManager in order for the various oauth2 classes to find it. This worked for me:

@Configuration
@EnableWebSecurity 
public class SecurityConfig extends WebSecurityConfigurerAdapter {

  @Autowired
  Users userDetailsService;

  @Autowired
  public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(userDetailsService);
  }

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
    // other stuff to configure your security
  }

}

I think if you changed the following starting at line 73, it may work for you:

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.parentAuthenticationManager(authenticationManager)
        .userDetailsService(userDetailsService);
}

You would also of course need to add @Autowired Users userDetailsService; somewhere in WebSecurityConfigurerAdapter

Other things I wanted to mention:

  1. This may be version specific, I'm on spring-security-oauth2 2.0.12
  2. I can't cite any sources for why this is the way it is, I'm not even sure if my solution is a real solution or a hack.
  3. The GlobalAuthenticationManagerConfigurer referred to in the guide is almost certainly a typo, I can't find that string anywhere in the source code for anything in Spring.

Add custom UserDetailsService to Spring Security OAuth2 app, How do I add the custom UserDetailsService below to this Spring OAuth2 sample​? The default user with default password is defined in the application.properties  Just having a bean that implements the UserDetailsService, in your Spring context, is enough. Spring Security will pick the UserDetailsService implementation you provided, and this will be used to


I ran into the same issue and originally had the same solution as Manan Mehta posted. Just recently, some version combination of spring security and spring oauth2 resulted in any attempt to refresh tokens resulting in an HTTP 500 error stating that UserDetailsService is required in my logs.

The relevant stack trace looks like:

java.lang.IllegalStateException: UserDetailsService is required.
at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter$UserDetailsServiceDelegator.loadUserByUsername(WebSecurityConfigurerAdapter.java:463)
at org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper.loadUserDetails(UserDetailsByNameServiceWrapper.java:68)
at org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider.authenticate(PreAuthenticatedAuthenticationProvider.java:103)
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:174)
at org.springframework.security.oauth2.provider.token.DefaultTokenServices.refreshAccessToken(DefaultTokenServices.java:150)

You can see at the bottom that the DefaultTokenServices is attempting to refresh the token. It then calls into an AuthenticationManager to re-authenticate (in case the user revoked permission or the user was deleted, etc.) but this is where it all unravels. You see at the top of the stack trace that UserDetailsServiceDelegator is what gets the call to loadUserByUsername instead of my beautiful UserDetailsService. Even though inside my WebSecurityConfigurerAdapter I set the UserDetailsService, there are two other WebSecurityConfigurerAdapters. One for the ResourceServerConfiguration and one for the AuthorizationServerSecurityConfiguration and those configurations never get the UserDetailsService that I set.

In tracing all the way through Spring Security to piece together what is going on, I found that there is a "local" AuthenticationManagerBuilder and a "global" AuthenticationManagerBuilder and we need to set it on the global version in order to have this information passed to these other builder contexts.

So, the solution I came up with was to get the "global" version in the same way the other contexts were getting the global version. Inside my WebSecurityConfigurerAdapter I had the following:

@Autowired
public void setApplicationContext(ApplicationContext context) {
    super.setApplicationContext(context);
    AuthenticationManagerBuilder globalAuthBuilder = context
            .getBean(AuthenticationManagerBuilder.class);
    try {
        globalAuthBuilder.userDetailsService(userDetailsService);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

And this worked. Other contexts now had my UserDetailsService. I leave this here for any brave soldiers who stumble upon this minefield in the future.

Spring Security 5 - Custom UserDetailsService example, The UserDetailsService is a core interface in Spring Security UserDetailsService for authentication in Spring MVC web application. Open pom.xml file of your maven project and add the following dependencies in it. pom​. Spring Boot really only pre-configures Spring Security for you, whenever you add the spring-boot-starter-security dependency to your Spring Boot project. Other than that, all security configuration is done with plain Spring Security concepts (think: WebSecurityConfigurerAdapter, authentication & authorization rules), which have nothing to do


My requirement was to get a database object off the back of the oauth2 email attribute. I found this question as I assumed that I need to create a custom user details service. Actually I need to implment the OidcUser interface and hook into that process.

Initially I thought it was the OAuth2UserService, but I've set up my AWS Cognito authentication provider so that it's open id connect..

//inside WebSecurityConfigurerAdapter

http
.oauth2Login()
.userInfoEndpoint()
.oidcUserService(new CustomOidcUserServiceImpl());

...

public class CustomOidcUserServiceImpl implements OAuth2UserService<OidcUserRequest, OidcUser> {

    private OidcUserService oidcUserService = new OidcUserService();

    @Override
    public OidcUser loadUser(OidcUserRequest userRequest) throws OAuth2AuthenticationException {
        OidcUser oidcUser = oidcUserService.loadUser(userRequest);
        return new CustomUserPrincipal(oidcUser);
    }
}

...

public class CustomUserPrincipal implements OidcUser {

    private OidcUser oidcUser;

    //forward all calls onto the included oidcUser
}

The custom service is where any bespoke logic can go. I plan on implementing UserDetails interface on my CustomUserPrincipal so that I can have different authentication mechanisms for live and test to facilitate automated ui testing.

Connecting Spring-Security-Oauth2 With Varying Data Sources, How do I add the custom UserDetailsService below to this Spring OAuth2 sample​? In Spring Boot 2, if we want our own security configuration, we can simply add a custom WebSecurityConfigurerAdapter. This will disable the default auto-configuration and enable our custom security configuration. Spring Boot 2 uses most of Spring Security’s defaults.


For anyone got UserDetailsService is required error when doing refresh token, and you confirm you already have UserDetailsService bean.

try add this:

@Configuration
public class GlobalSecurityConfig extends GlobalAuthenticationConfigurerAdapter {
    private UserDetailsService userDetailsService;

    public GlobalSecurityConfig(UserDetailsService userDetailsService) {
        this.userDetailsService = userDetailsService;
    }

    @Override
    public void init(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService);
    }
}

This is my try and error, maybe not work for you.

By the way, if you give up "guess" which bean will pick by spring, you can extends AuthorizationServerConfigurerAdapter and WebSecurityConfigurerAdapter and config all stuff by yourself, but I think it's lose power of spring autoconfig. Why I need config everything if I just need customize some config?

Spring Security: Database-backed UserDetailsService, How to Configure OAuth2 Authentication With Spring-Security-Oauth2 or a separate application) serves resources that are protected by the OAuth2 token. Now, let's implement an interface called UserDetailsService. However, as my use case also requires the list of groups in which the user is in,  First of all, to use Spring Method Security, we need to add the spring-security-config dependency: <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-config</artifactId> </dependency> We can find its latest version on Maven Central.


Spring Security Custom Authentication Provider, Spring Security: Authentication with a Database-backed full material focused on the new OAuth2 stack in Spring Security 5: All we need to do to enable our custom UserDetailsService is add it to our application context as  Spring Boot really only pre-configures Spring Security for you, whenever you add the spring-boot-starter-security dependency to your Spring Boot project. Other than that, all security configuration is done with plain Spring Security concepts (think: WebSecurityConfigurerAdapter, authentication & authorization rules), which have nothing to do


Spring Security OAuth2 User Registration, How to Set Up a Custom Authentication Provider with Spring Security and the full material focused on the new OAuth2 stack in Spring Security 5: details from a simple, read-only user DAO – the UserDetailsService. use the credentials This is because authorities are of course application specific. Add custom login page in oauth2Login () element. User can choose login options with either custom email and password or social login with Google OAuth. After a successful login, JWT token should be generated and token-based authentication is enabled and user is redirected to /home. Spring Security OAuth Configuration


Secure Spring REST With Spring Security and OAuth2, Learn how to add custom user registration in an existing spring boot security OAuth2 application along with social login with Google. Here, we have injected UserDetailsService required by auth manager to fetch the users  Custom UserDetailsService Now – let's check out the authentication process. We're going to see how to retrieve the user within our custom UserDetailsService , and how to map the right set of authorities from the roles and privileges the user has assigned: