diff --git a/config/src/main/kotlin/org/springframework/security/config/web/server/ServerOAuth2ResourceServerDsl.kt b/config/src/main/kotlin/org/springframework/security/config/web/server/ServerOAuth2ResourceServerDsl.kt index c4dfc45e7f..d78089859f 100644 --- a/config/src/main/kotlin/org/springframework/security/config/web/server/ServerOAuth2ResourceServerDsl.kt +++ b/config/src/main/kotlin/org/springframework/security/config/web/server/ServerOAuth2ResourceServerDsl.kt @@ -20,6 +20,7 @@ import org.springframework.security.authentication.ReactiveAuthenticationManager import org.springframework.security.web.server.ServerAuthenticationEntryPoint import org.springframework.security.web.server.authentication.ServerAuthenticationConverter import org.springframework.security.web.server.authentication.ServerAuthenticationFailureHandler +import org.springframework.security.web.server.authentication.ServerAuthenticationSuccessHandler import org.springframework.security.web.server.authorization.ServerAccessDeniedHandler import org.springframework.web.server.ServerWebExchange @@ -35,6 +36,8 @@ import org.springframework.web.server.ServerWebExchange * @property bearerTokenConverter the [ServerAuthenticationConverter] to use for requests authenticating with * Bearer Tokens. * @property authenticationManagerResolver the [ReactiveAuthenticationManagerResolver] to use. + * @property authenticationSuccessHandler the [ServerAuthenticationSuccessHandler] to use after + * authentication success. */ @ServerSecurityMarker class ServerOAuth2ResourceServerDsl { @@ -43,6 +46,7 @@ class ServerOAuth2ResourceServerDsl { var authenticationEntryPoint: ServerAuthenticationEntryPoint? = null var bearerTokenConverter: ServerAuthenticationConverter? = null var authenticationManagerResolver: ReactiveAuthenticationManagerResolver? = null + var authenticationSuccessHandler: ServerAuthenticationSuccessHandler? = null private var jwt: ((ServerHttpSecurity.OAuth2ResourceServerSpec.JwtSpec) -> Unit)? = null private var opaqueToken: ((ServerHttpSecurity.OAuth2ResourceServerSpec.OpaqueTokenSpec) -> Unit)? = null @@ -115,6 +119,7 @@ class ServerOAuth2ResourceServerDsl { authenticationEntryPoint?.also { oauth2ResourceServer.authenticationEntryPoint(authenticationEntryPoint) } bearerTokenConverter?.also { oauth2ResourceServer.bearerTokenConverter(bearerTokenConverter) } authenticationManagerResolver?.also { oauth2ResourceServer.authenticationManagerResolver(authenticationManagerResolver!!) } + authenticationSuccessHandler?.also { oauth2ResourceServer.authenticationSuccessHandler(authenticationSuccessHandler) } jwt?.also { oauth2ResourceServer.jwt(jwt) } opaqueToken?.also { oauth2ResourceServer.opaqueToken(opaqueToken) } } diff --git a/config/src/test/kotlin/org/springframework/security/config/web/server/ServerOAuth2ResourceServerDslTests.kt b/config/src/test/kotlin/org/springframework/security/config/web/server/ServerOAuth2ResourceServerDslTests.kt index 3067d18012..99fa26bfc2 100644 --- a/config/src/test/kotlin/org/springframework/security/config/web/server/ServerOAuth2ResourceServerDslTests.kt +++ b/config/src/test/kotlin/org/springframework/security/config/web/server/ServerOAuth2ResourceServerDslTests.kt @@ -17,6 +17,7 @@ package org.springframework.security.config.web.server import io.mockk.every +import io.mockk.mockk import io.mockk.mockkObject import io.mockk.verify import org.junit.jupiter.api.Test @@ -37,6 +38,7 @@ import org.springframework.security.web.server.SecurityWebFilterChain import org.springframework.security.web.server.WebFilterExchange import org.springframework.security.web.server.authentication.HttpStatusServerEntryPoint import org.springframework.security.web.server.authentication.ServerAuthenticationFailureHandler +import org.springframework.security.web.server.authentication.ServerAuthenticationSuccessHandler import org.springframework.security.web.server.authorization.HttpStatusServerAccessDeniedHandler import org.springframework.test.web.reactive.server.WebTestClient import org.springframework.web.reactive.config.EnableWebFlux @@ -183,6 +185,46 @@ class ServerOAuth2ResourceServerDslTests { } + @Test + fun `request when custom authentication success handler then success handler used`() { + this.spring.register(AuthenticationSuccessHandlerConfig::class.java).autowire() + every { + AuthenticationSuccessHandlerConfig.SUCCESS_HANDLER.onAuthenticationSuccess(any(), any()) + } returns Mono.empty() + + this.client.get() + .uri("/") + .headers { it.setBearerAuth(validJwt) } + .exchange() + + verify(exactly = 1) { AuthenticationSuccessHandlerConfig.SUCCESS_HANDLER.onAuthenticationSuccess(any(), any()) } + } + + @Configuration + @EnableWebFluxSecurity + @EnableWebFlux + open class AuthenticationSuccessHandlerConfig { + + companion object { + val SUCCESS_HANDLER: ServerAuthenticationSuccessHandler = mockk() + } + + @Bean + open fun springWebFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain { + return http { + authorizeExchange { + authorize(anyExchange, authenticated) + } + oauth2ResourceServer { + authenticationSuccessHandler = SUCCESS_HANDLER + jwt { + publicKey = publicKey() + } + } + } + } + } + @Test fun `request when custom bearer token converter configured then custom converter used`() { this.spring.register(BearerTokenConverterConfig::class.java).autowire()