Skip to content
This repository was archived by the owner on Feb 23, 2023. It is now read-only.

Spring Security - AuthenticationFailureBadCredentialsEvent has no suitable constructor #1521

Closed
Saljack opened this issue Mar 4, 2022 · 3 comments · Fixed by #1531
Closed
Labels
type: compatibility Native image compatibility issue
Milestone

Comments

@Saljack
Copy link

Saljack commented Mar 4, 2022

I tried to create a simple native application with Spring Native 0.11.3 and with spring-boot-starter-oauth2-client (it should be supported regarding the Spring Native documentation) and I use GraalVM 22.0.0.2 Java 17 CE. It is just runner which calls a REST API endpoint secured with OAuth2 and using WebClient. But I am not able to start native application and the error is AuthenticationFailureBadCredentialsEvent has no suitable constructor. Normal jar application works fine.

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'authenticationEventPublisher': Unexpected exception during bean creation; nested exception is java.lang.RuntimeException: Authentication event class org.springframework.security.authentication.event.AuthenticationFailureBadCredentialsEvent has no suitable constructor
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:555) ~[na:na]
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[na:na]
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[na:na]
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[na:na]
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[na:na]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:953) ~[na:na]
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) ~[na:na]
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[na:na]
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:740) ~[downloader:2.6.4]
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:415) ~[downloader:2.6.4]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) ~[downloader:2.6.4]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1312) ~[downloader:2.6.4]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1301) ~[downloader:2.6.4]
        at de.fiskal.client.downloader.DownloaderApplication.main(DownloaderApplication.java:11) ~[downloader:0.0.1-SNAPSHOT]
Caused by: java.lang.RuntimeException: Authentication event class org.springframework.security.authentication.event.AuthenticationFailureBadCredentialsEvent has no suitable constructor
        at org.springframework.security.authentication.DefaultAuthenticationEventPublisher.addMapping(DefaultAuthenticationEventPublisher.java:209) ~[na:na]
        at org.springframework.security.authentication.DefaultAuthenticationEventPublisher.<init>(DefaultAuthenticationEventPublisher.java:82) ~[na:na]
        at org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration.authenticationEventPublisher(SecurityAutoConfiguration.java:50) ~[downloader:2.6.4]
        at org.springframework.aot.ContextBootstrapInitializer.lambda$initialize$30(ContextBootstrapInitializer.java:176) ~[na:na]
        at org.springframework.aot.beans.factory.BeanDefinitionRegistrar$ThrowableFunction.apply(BeanDefinitionRegistrar.java:294) ~[na:na]
        at org.springframework.aot.beans.factory.InjectedElementResolver.create(InjectedElementResolver.java:67) ~[na:na]
        at org.springframework.aot.beans.factory.BeanDefinitionRegistrar$BeanInstanceContext.create(BeanDefinitionRegistrar.java:211) ~[na:na]
        at org.springframework.aot.ContextBootstrapInitializer.lambda$initialize$31(ContextBootstrapInitializer.java:176) ~[na:na]
        at org.springframework.aot.beans.factory.BeanDefinitionRegistrar$ThrowableFunction.apply(BeanDefinitionRegistrar.java:294) ~[na:na]
        at org.springframework.aot.beans.factory.BeanDefinitionRegistrar.lambda$instanceSupplier$0(BeanDefinitionRegistrar.java:115) ~[na:na]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainFromSupplier(AbstractAutowireCapableBeanFactory.java:1249) ~[na:na]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1191) ~[na:na]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582) ~[na:na]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[na:na]
        ... 13 common frames omitted

There is WebClient configuration (nothing special):

@Configuration
public class WebClientConfig {

  private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(WebClientConfig.class);

  private static final String DF = "df";
  public static final String OAUTH2 = "oauth";

  @Value("${username}")
  private String username;

  @Value("${password}")
  private String password;

  @Bean
  @Qualifier(OAUTH2)
  WebClient webClientOAuth(WebClient.Builder webClientBuilder,
      ReactiveOAuth2AuthorizedClientManager authorizedClientManager) {

    if (username == null) {
      log.error("Username must be defined. Add --username=your_username");
      throw new IllegalArgumentException("Username must be defined. Add --username=your_username");
    }

    if (password == null) {
      log.error("Password must be defined. Add --password=your_password");
      throw new IllegalArgumentException("Password must be defined. Add --password=your_password");
    }

    ServerOAuth2AuthorizedClientExchangeFilterFunction oauth2Client = new ServerOAuth2AuthorizedClientExchangeFilterFunction(
        authorizedClientManager);
    oauth2Client.setDefaultOAuth2AuthorizedClient(true);
    oauth2Client.setDefaultClientRegistrationId(DF);

    return webClientBuilder
        .filter(oauth2Client)
        .build();
  }

  @Bean
  WebClient webClient(WebClient.Builder webClientBuilder,
      ReactiveOAuth2AuthorizedClientManager authorizedClientManager) {
    return webClientBuilder
        .build();
  }

  @Bean
  public ReactiveOAuth2AuthorizedClientManager authorizedClientManager(
      ReactiveClientRegistrationRepository clientRegistrationRepository,
      ReactiveOAuth2AuthorizedClientService authorizedClientService) {

    ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = ReactiveOAuth2AuthorizedClientProviderBuilder
        .builder()
        .password()
        .build();

    AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager authorizedClientManager = new AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager(
        clientRegistrationRepository, authorizedClientService);
    authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
    authorizedClientManager
        .setContextAttributesMapper(req -> Mono.just(Map.of(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME,
            username, OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, password)));
    return authorizedClientManager;
  }
}

and application yaml:

spring:
  main:
    web-application-type: NONE
    banner-mode: off
  security:
    oauth2:
     client:
       registration:
          df:
           client-id: df-api
           authorization-grant-type: password
       provider:
         df:
           token-uri: ${url}/auth/realms/df/protocol/openid-connect/token

I can try to create sample application if it helps you.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Mar 4, 2022
@Saljack
Copy link
Author

Saljack commented Mar 4, 2022

And here is an example project:
https://github.com/Saljack/native-downloader/

@Saljack
Copy link
Author

Saljack commented Mar 4, 2022

I found a workaround. Because this application does not use @EnableWebFluxSecurity respectively there is no WebFluxSecurityConfiguration or WebSecurityConfiguration I have to import hints for security manually:

@NativeHint(imports = {CommonSecurityTypes.class, CommonSecurityResources.class})

I feel it is pretty fragile and pretty hard to find how to fix these things.

@sdeleuze
Copy link
Contributor

sdeleuze commented Mar 7, 2022

@eleftherias Could you please take care of that one?

@sdeleuze sdeleuze added type: compatibility Native image compatibility issue and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Mar 7, 2022
@sdeleuze sdeleuze added this to the 0.11.4 milestone Mar 7, 2022
eleftherias added a commit to eleftherias/spring-native that referenced this issue Mar 11, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
type: compatibility Native image compatibility issue
Development

Successfully merging a pull request may close this issue.

3 participants