diff --git a/build.gradle b/build.gradle index 7f0839e..e7866cf 100644 --- a/build.gradle +++ b/build.gradle @@ -15,7 +15,7 @@ repositories { } dependencies { - implementation platform('run.halo.tools.platform:plugin:2.6.0-SNAPSHOT') + implementation platform('run.halo.tools.platform:plugin:2.17.0-SNAPSHOT') compileOnly 'run.halo.app:api' testImplementation 'run.halo.app:api' @@ -29,5 +29,5 @@ test { } halo { - version = '2.13' + version = '2.17' } diff --git a/src/main/java/run/halo/oauth/Oauth2Authenticator.java b/src/main/java/run/halo/oauth/Oauth2Authenticator.java index c49a819..3c2ac41 100644 --- a/src/main/java/run/halo/oauth/Oauth2Authenticator.java +++ b/src/main/java/run/halo/oauth/Oauth2Authenticator.java @@ -37,6 +37,7 @@ import org.springframework.web.util.UriUtils; import reactor.core.publisher.Mono; import run.halo.app.security.AdditionalWebFilter; +import run.halo.app.security.LoginHandlerEnhancer; /** * Oauth2 authenticator. @@ -94,6 +95,10 @@ AuthenticationWebFilter createAuthenticationWebFilter() { return authenticationFilter; } + private LoginHandlerEnhancer getLoginHandlerEnhancer() { + return oauth2LoginConfiguration.getLoginHandlerEnhancer(); + } + class SocialLoginAuthenticationWebFilter extends OAuth2LoginAuthenticationWebFilter { private final ServerRedirectStrategy redirectStrategy = new DefaultServerRedirectStrategy(); @@ -211,7 +216,8 @@ Mono handleAuthenticationSuccess(Authentication authentication, redirectUri) ) .contextWrite( - ReactiveSecurityContextHolder.withSecurityContext(Mono.just(securityContext))); + ReactiveSecurityContextHolder.withSecurityContext(Mono.just(securityContext))) + .then(getLoginHandlerEnhancer().onLoginSuccess(exchange, authentication)); } Mono authenticationSuccessRedirection(WebFilterExchange webFilterExchange, diff --git a/src/main/java/run/halo/oauth/Oauth2LoginConfiguration.java b/src/main/java/run/halo/oauth/Oauth2LoginConfiguration.java index 163b061..0cbb46b 100644 --- a/src/main/java/run/halo/oauth/Oauth2LoginConfiguration.java +++ b/src/main/java/run/halo/oauth/Oauth2LoginConfiguration.java @@ -1,18 +1,13 @@ package run.halo.oauth; -import java.net.URI; -import java.util.Optional; import lombok.Getter; -import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.security.authentication.DelegatingReactiveAuthenticationManager; import org.springframework.security.authentication.ReactiveAuthenticationManager; -import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper; import org.springframework.security.core.authority.mapping.SimpleAuthorityMapper; import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientService; -import org.springframework.security.oauth2.client.authentication.OAuth2LoginAuthenticationToken; import org.springframework.security.oauth2.client.authentication.OAuth2LoginReactiveAuthenticationManager; import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeGrantRequest; import org.springframework.security.oauth2.client.endpoint.ReactiveOAuth2AccessTokenResponseClient; @@ -26,12 +21,7 @@ import org.springframework.security.oauth2.client.userinfo.DefaultReactiveOAuth2UserService; import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest; import org.springframework.security.oauth2.client.userinfo.ReactiveOAuth2UserService; -import org.springframework.security.oauth2.client.web.server.AuthenticatedPrincipalServerOAuth2AuthorizedClientRepository; -import org.springframework.security.oauth2.client.web.server.OAuth2AuthorizationRequestRedirectWebFilter; -import org.springframework.security.oauth2.client.web.server.ServerAuthorizationRequestRepository; -import org.springframework.security.oauth2.client.web.server.ServerOAuth2AuthorizationCodeAuthenticationTokenConverter; -import org.springframework.security.oauth2.client.web.server.ServerOAuth2AuthorizedClientRepository; -import org.springframework.security.oauth2.client.web.server.WebSessionOAuth2ServerAuthorizationRequestRepository; +import org.springframework.security.oauth2.client.web.server.*; import org.springframework.security.oauth2.core.OAuth2AuthenticationException; import org.springframework.security.oauth2.core.OAuth2AuthorizationException; import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; @@ -42,19 +32,17 @@ import org.springframework.security.web.server.ServerRedirectStrategy; import org.springframework.security.web.server.WebFilterExchange; import org.springframework.security.web.server.authentication.RedirectServerAuthenticationFailureHandler; -import org.springframework.security.web.server.authentication.RedirectServerAuthenticationSuccessHandler; 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.savedrequest.ServerRequestCache; import org.springframework.security.web.server.savedrequest.WebSessionServerRequestCache; import org.springframework.security.web.server.util.matcher.PathPatternParserServerWebExchangeMatcher; import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher; import org.springframework.stereotype.Component; import org.springframework.util.ClassUtils; -import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; import run.halo.app.extension.ReactiveExtensionClient; +import run.halo.app.security.LoginHandlerEnhancer; /** * Oauth2 login configuration. @@ -82,10 +70,14 @@ public final class Oauth2LoginConfiguration { private final OAuth2AuthorizationRequestRedirectWebFilter redirectWebFilter; private final ReactiveExtensionClient extensionClient; + + private final LoginHandlerEnhancer loginHandlerEnhancer; + private ServerRequestCache requestCache = new WebSessionServerRequestCache(); - public Oauth2LoginConfiguration(ReactiveExtensionClient extensionClient) { + public Oauth2LoginConfiguration(ReactiveExtensionClient extensionClient, LoginHandlerEnhancer loginHandlerEnhancer) { this.extensionClient = extensionClient; + this.loginHandlerEnhancer = loginHandlerEnhancer; Initializer initializer = new Initializer(); this.authenticationManager = initializer.getAuthenticationManager(); @@ -112,7 +104,14 @@ public void setRequestCache(ServerRequestCache requestCache) { class Initializer { ServerAuthenticationFailureHandler getAuthenticationFailureHandler() { - return new RedirectServerAuthenticationFailureHandler("/console/login?error"); + return new RedirectServerAuthenticationFailureHandler("/console/login?error") { + @Override + public Mono onAuthenticationFailure(WebFilterExchange webFilterExchange, + AuthenticationException exception) { + return loginHandlerEnhancer.onLoginFailure(webFilterExchange.getExchange(), exception) + .then(super.onAuthenticationFailure(webFilterExchange, exception)); + } + }; } GrantedAuthoritiesMapper getAuthoritiesMapper() { diff --git a/src/main/resources/plugin.yaml b/src/main/resources/plugin.yaml index ecbf759..d037f99 100644 --- a/src/main/resources/plugin.yaml +++ b/src/main/resources/plugin.yaml @@ -6,7 +6,7 @@ metadata: store.halo.run/app-id: app-ESVDK spec: enabled: true - requires: ">=2.6.0" + requires: ">=2.17.0" author: name: Halo website: https://github.com/halo-dev diff --git a/src/test/java/run/halo/oauth/Oauth2LoginConfigurationTest.java b/src/test/java/run/halo/oauth/Oauth2LoginConfigurationTest.java index 4a029fc..2a17500 100644 --- a/src/test/java/run/halo/oauth/Oauth2LoginConfigurationTest.java +++ b/src/test/java/run/halo/oauth/Oauth2LoginConfigurationTest.java @@ -5,6 +5,7 @@ import org.junit.jupiter.api.Test; import run.halo.app.extension.ReactiveExtensionClient; +import run.halo.app.security.LoginHandlerEnhancer; /** * Tests for {@link Oauth2LoginConfiguration}. @@ -17,8 +18,9 @@ class Oauth2LoginConfigurationTest { @Test void constructor() { ReactiveExtensionClient extensionClient = mock(ReactiveExtensionClient.class); + var loginHandlerEnhancer = mock(LoginHandlerEnhancer.class); Oauth2LoginConfiguration oauth2LoginConfiguration = - new Oauth2LoginConfiguration(extensionClient); + new Oauth2LoginConfiguration(extensionClient, loginHandlerEnhancer); assertNotNull(oauth2LoginConfiguration); }