Search code examples
spring-security-oauth2azure-spring-boot

Adding a custom OidcUserService to work with Spring Azure AAD OidcUserService


We have the following Spring Security Configuration class that extends Spring Azure configuration adapter and want to add a custom OidcUserService to the userInfo callback. We have 2 separate projects, a prototype one and our real project. We used the prototype to prove that it can work, and once it worked move it to our real project. Both projects are identical in configuration, pom/libraries on the class path, etc. But in the real project we get an error stating there is a circular dependency in the configuration. We can't figure out how to resolve this problem.

EDIT: Some more findings, It appears Spring in the real project is injecting our custom OidcUserService into the AADO Security beans instead of using their own, whereas the prototype puts in the correct AADO OidcUserService. Like the order of bean instantiation is different between projects even though we do not specify order in either project.

Here is the code in both projects for the configuration. The custom OidcUserService is identical to each project. Copy/Pasted from one project to the other, including this configuration.

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
class AADOAuth2LoginSecurityConfig extends AADWebSecurityConfigurerAdapter {

@Resource
OAuth2UserService<OidcUserRequest, OidcUser> customOidcUserService;

@Override
protected void configure(HttpSecurity http) throws Exception {
    super.configure(http);
    http
            .authorizeRequests()
            .antMatchers("/", "/login", "/*.js", "/*.css").permitAll()
            .anyRequest().authenticated()
            .and()
            .csrf()
            .disable()
            .oauth2Login(oauth2Login ->
                    oauth2Login.userInfoEndpoint(userInfoEndpoint ->
                            userInfoEndpoint.oidcUserService(customOidcUserService)
                    )
            );
}

}

Here is the custom service, in case you wanted to see it.

@Service
public class CustomOidcUserService implements OAuth2UserService<OidcUserRequest, OidcUser> {

final private OAuth2UserService<OidcUserRequest, OidcUser> aadoAuth2UserService;

public CustomOidcUserService(OAuth2UserService<OidcUserRequest, OidcUser> aadoAuth2UserService) {
    this.aadoAuth2UserService = aadoAuth2UserService;
}

public OidcUser loadUser(OidcUserRequest userRequest) throws OAuth2AuthenticationException {
    OidcUser oidcUser = aadoAuth2UserService.loadUser(userRequest);
    //Custom code would go here
    return oidcUser;
}

}


Solution

    1. There is @ConditionalOnMissingBean in the source code of azure-spring-boot, so if you defined CustomOidcUserService as a bean, AADOAuth2UserService bean will not be created.

    2. But in the real project we get an error stating there is a circular dependency in the configuration. We can't figure out how to resolve this problem.. Could you please share the log?

    3. whereas the prototype puts in the correct AADO OidcUserService, do you mean the correct AADO OidcUserService should be AADOAuth2UserService?

    4. For such kind of problems, it's better to create an issue in the GitHub, and describe how to reproduce your problem. So you can create an issue here.