springspring-bootauthorization

Spring Authorization Server provide "No AuthenticationProvider found"


I'm trying to set up an authorization server using spring-boot-starter-oauth2-authorization-server. The thing is that when I try to enter my login and password, an error occurs "No AuthenticationProvider found". Please help me fix this.

SecurityConfig class

@EnableWebSecurity
@Configuration(proxyBeanMethods = false)
public class SecurityConfig {

    @Bean
    public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests(authorize ->
                authorize.anyRequest().authenticated())
                .csrf(AbstractHttpConfigurer::disable);
        return http.formLogin(Customizer.withDefaults()).build();
    }

    @Bean
    public UserDetailsService userDetailsService() {
        UserDetails user = User.builder()
                .username("admin")
                .password("{noop}password")
                .roles("USER")
                .build();
        return new InMemoryUserDetailsManager(user);
    }

}

AuthorizationServerConfig class

@Configuration
@RequiredArgsConstructor
public class AuthorizationServerConfig {

    private final OAuth2AuthorizationServerProperties authorizationServerProperties;

    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public SecurityFilterChain authServerSecurityFilterChain(HttpSecurity http) throws Exception {
        OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
        http.exceptionHandling(exception ->
                exception.authenticationEntryPoint(
                        new LoginUrlAuthenticationEntryPoint("/login")));
        return http.build();
    }

    @Bean
    public RegisteredClientRepository registeredClientRepository() {
        return new InMemoryRegisteredClientRepository(
                RegisteredClient.withId("test-client-id")
                        .clientName("Test Client")
                        .clientId("test-client")
                        .clientSecret("{noop}test-client")
                        .redirectUri("http://localhost:5000/code")
                        .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
                        .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
                        .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
                        .authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
                        .build()
        );
    }

    @Bean
    public JWKSource<SecurityContext> jwkSource() {
        KeyPair keyPair = generateRsaKey();
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
        RSAKey rsaKey = new RSAKey.Builder(publicKey)
                .privateKey(privateKey)
                .keyID(UUID.randomUUID().toString())
                .build();
        JWKSet jwkSet = new JWKSet(rsaKey);
        return ((jwkSelector, securityContext) -> jwkSelector.select(jwkSet));
    }

    private static KeyPair generateRsaKey() {
        KeyPair keyPair;
        try {
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
            keyPairGenerator.initialize(2048);
            keyPair = keyPairGenerator.generateKeyPair();
        } catch (Exception ex) {
            throw new IllegalStateException(ex);
        }
        return keyPair;
    }

    @Bean
    public JwtDecoder jwtDecoder(JWKSource<SecurityContext> jwkSource) {
        return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource);
    }

    @Bean
    public AuthorizationServerSettings authorizationServerSettings() {
        return AuthorizationServerSettings.builder()
                .issuer(authorizationServerProperties.getIssuer())
                .build();
    }

}

application.yaml

server:
  port: 7777

logging:
  level:
    org:
      springframework:
        security: trace

spring:
  application:
    name: j-sso
  security:
    oauth2:
      authorizationserver:
        issuer-url: http://localhost:7777

trace log

2024-11-13T01:03:51.717+03:00 TRACE 3596 --- [j-sso] [nio-7777-exec-6] o.s.s.w.s.HttpSessionRequestCache        : Did not save request since it did not match [And [Ant [pattern='/**', GET], Not [Ant [pattern='/**/favicon.*']], Not [MediaTypeRequestMatcher [contentNegotiationStrategy=org.springframework.web.accept.ContentNegotiationManager@1858a268, matchingMediaTypes=[application/json], useEquals=false, ignoredMediaTypes=[*/*]]], Not [RequestHeaderRequestMatcher [expectedHeaderName=X-Requested-With, expectedHeaderValue=XMLHttpRequest]], Not [MediaTypeRequestMatcher [contentNegotiationStrategy=org.springframework.web.accept.ContentNegotiationManager@1858a268, matchingMediaTypes=[multipart/form-data], useEquals=false, ignoredMediaTypes=[*/*]]], Not [MediaTypeRequestMatcher [contentNegotiationStrategy=org.springframework.web.accept.ContentNegotiationManager@1858a268, matchingMediaTypes=[text/event-stream], useEquals=false, ignoredMediaTypes=[*/*]]]]]
2024-11-13T01:03:51.717+03:00 DEBUG 3596 --- [j-sso] [nio-7777-exec-6] s.w.a.DelegatingAuthenticationEntryPoint : Trying to match using And [Not [RequestHeaderRequestMatcher [expectedHeaderName=X-Requested-With, expectedHeaderValue=XMLHttpRequest]], MediaTypeRequestMatcher [contentNegotiationStrategy=org.springframework.web.accept.ContentNegotiationManager@1858a268, matchingMediaTypes=[application/xhtml+xml, image/*, text/html, text/plain], useEquals=false, ignoredMediaTypes=[*/*]]]
2024-11-13T01:03:51.718+03:00 DEBUG 3596 --- [j-sso] [nio-7777-exec-6] s.w.a.DelegatingAuthenticationEntryPoint : Match found! Executing org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint@2fd72332
2024-11-13T01:03:51.718+03:00 DEBUG 3596 --- [j-sso] [nio-7777-exec-6] o.s.s.web.DefaultRedirectStrategy        : Redirecting to http://localhost:7777/login
2024-11-13T01:03:51.718+03:00 TRACE 3596 --- [j-sso] [nio-7777-exec-6] o.s.s.w.header.writers.HstsHeaderWriter  : Not injecting HSTS header since it did not match request to [Is Secure]
2024-11-13T01:03:51.732+03:00 TRACE 3596 --- [j-sso] [nio-7777-exec-7] o.s.security.web.FilterChainProxy        : Trying to match request against DefaultSecurityFilterChain [RequestMatcher=any request, Filters=[org.springframework.security.web.session.DisableEncodeUrlFilter@9fdc290, org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@1fc0cdb4, org.springframework.security.web.context.SecurityContextHolderFilter@7793ad58, org.springframework.security.web.header.HeaderWriterFilter@62765aec, org.springframework.security.web.csrf.CsrfFilter@5dfe23e8, org.springframework.security.web.authentication.logout.LogoutFilter@5af64ce0, org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter@49f3ff41, org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter@4207852d, org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter@733e2d75, org.springframework.security.web.authentication.www.BasicAuthenticationFilter@4f2d014a, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@16132f21, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@4640195a, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@2a4db2b5, org.springframework.security.web.access.ExceptionTranslationFilter@50b0afd7, org.springframework.security.web.access.intercept.AuthorizationFilter@56846330]] (1/1)
2024-11-13T01:03:51.733+03:00 DEBUG 3596 --- [j-sso] [nio-7777-exec-7] o.s.security.web.FilterChainProxy        : Securing GET /login
2024-11-13T01:03:51.733+03:00 TRACE 3596 --- [j-sso] [nio-7777-exec-7] o.s.security.web.FilterChainProxy        : Invoking DisableEncodeUrlFilter (1/15)
2024-11-13T01:03:51.733+03:00 TRACE 3596 --- [j-sso] [nio-7777-exec-7] o.s.security.web.FilterChainProxy        : Invoking WebAsyncManagerIntegrationFilter (2/15)
2024-11-13T01:03:51.733+03:00 TRACE 3596 --- [j-sso] [nio-7777-exec-7] o.s.security.web.FilterChainProxy        : Invoking SecurityContextHolderFilter (3/15)
2024-11-13T01:03:51.733+03:00 TRACE 3596 --- [j-sso] [nio-7777-exec-7] o.s.security.web.FilterChainProxy        : Invoking HeaderWriterFilter (4/15)
2024-11-13T01:03:51.733+03:00 TRACE 3596 --- [j-sso] [nio-7777-exec-7] o.s.security.web.FilterChainProxy        : Invoking CsrfFilter (5/15)
2024-11-13T01:03:51.733+03:00 TRACE 3596 --- [j-sso] [nio-7777-exec-7] o.s.security.web.csrf.CsrfFilter         : Did not protect against CSRF since request did not match CsrfNotRequired [TRACE, HEAD, GET, OPTIONS]
2024-11-13T01:03:51.733+03:00 TRACE 3596 --- [j-sso] [nio-7777-exec-7] o.s.security.web.FilterChainProxy        : Invoking LogoutFilter (6/15)
2024-11-13T01:03:51.733+03:00 TRACE 3596 --- [j-sso] [nio-7777-exec-7] o.s.s.w.a.logout.LogoutFilter            : Did not match request to Ant [pattern='/logout', POST]
2024-11-13T01:03:51.733+03:00 TRACE 3596 --- [j-sso] [nio-7777-exec-7] o.s.security.web.FilterChainProxy        : Invoking UsernamePasswordAuthenticationFilter (7/15)
2024-11-13T01:03:51.733+03:00 TRACE 3596 --- [j-sso] [nio-7777-exec-7] w.a.UsernamePasswordAuthenticationFilter : Did not match request to Ant [pattern='/login', POST]
2024-11-13T01:03:51.734+03:00 TRACE 3596 --- [j-sso] [nio-7777-exec-7] o.s.security.web.FilterChainProxy        : Invoking DefaultLoginPageGeneratingFilter (8/15)
2024-11-13T01:03:51.734+03:00 TRACE 3596 --- [j-sso] [nio-7777-exec-7] o.s.s.w.header.writers.HstsHeaderWriter  : Not injecting HSTS header since it did not match request to [Is Secure]

Error enter image description here

I tried to set up mine like this https://wankhedeshubham.medium.com/spring-boot-security-with-userdetailsservice-and-custom-authentication-provider-3df3a188993f but it didn't help me.

Link to github repo: https://github.com/HaHhaRr/AuthServer


Solution

  • After looking at the Github, the main reason for your initial error is that the class marked with @SpringBootApplication is inside another package as the rest of the configuration classes.

    By default, Spring Boot scans for packages starting with the package that the @SpringBootApplication annotated class is in, and also sub-packages in that folder. The app isn't aware of the classes in com.haharr.security package.

    And that is also the reason why it works when you define UserDetailsService inside the Main class annotated with @SpringBootApplication. The rest of classes in other packages are in fact ignored and the app works thanks to autoconfigurations.

    Although the app can be configured to look for components in other places, I strongly suggest to follow the best practices and move the AuthorizationServerApplication one package (folder) up, in com.haharr pacakage (from com.haharr.authorizationserver package).

    After that, another whole set of problems to be solved, but that is food for another thread and most likely the tutorials can help with them.