OAuth2 client with Spring Boot 3

With Spring Boot 3 some classes were deprecated and also the Keycloak adapter and the admin client stopped working in an application I am maintaining. In https://blog.coffeebeans.at/archives/1904 I already showed how to instantiate a WebClient which is the new way Spring wants us to call external APIs – not considering external libs like feign now. In Spring Security there is also an integration for OAuth2/OIDC compliant authentication. Taking the application mentioned above you need to have 2 dependencies in place:

    implementation("org.springframework.boot:spring-boot-starter-security")
    implementation("org.springframework.security:spring-security-oauth2-client")

In your config you need to configure the OIDC server:

spring:
  security:
    oauth2:
      client:
        registration:
          keycloak:
            client-id: <id>
            client-secret: <secret>
            authorization-grant-type: client_credentials
        provider:
          keycloak:
            token-uri: <server-url>/realms/<realm>/protocol/openid-connect/token

In the method you create your WebClient you need to add an oauth filter:

    @Bean
    @Qualifier("keycloak")
    @ConditionalOnMissingBean
    fun keycloakWebClient(
      clientRegistrations: ReactiveClientRegistrationRepository,
      authorizedClientService: ReactiveOAuth2AuthorizedClientService,
    ): WebClient {

        val oauth = ServerOAuth2AuthorizedClientExchangeFilterFunction(
                AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager(
                        clientRegistrations, authorizedClientService
                )
        );
        oauth.setDefaultClientRegistrationId("keycloak");

        return WebClient.builder()
            .exchangeStrategies(ExchangeStrategies
                .builder()
                .codecs { clientDefaultCodecsConfigurer: ClientCodecConfigurer ->
                    clientDefaultCodecsConfigurer.defaultCodecs()
                        .jackson2JsonEncoder(Jackson2JsonEncoder(jsonMapper, MediaType.APPLICATION_JSON))
                    clientDefaultCodecsConfigurer.defaultCodecs()
                        .jackson2JsonDecoder(Jackson2JsonDecoder(jsonMapper, MediaType.APPLICATION_JSON))
                }.build()
            )
            .filter(WebClientLoggerBuilder.logRequest())
            .filter(oauth)
            .build()
    }

This results in a WebClient instance using OAuth2 authentication with the server you configured for all calls you use it for. The mapping “keycloak” refers to the key “keycloak” in your application.yml’s spring.security.oauth2.client.registration and spring.security.oauth2.client.provider.