diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/reactive/EnableWebFluxSecurity.java b/config/src/main/java/org/springframework/security/config/annotation/web/reactive/EnableWebFluxSecurity.java
index d1f2b2bb0f..3843bf9b92 100644
--- a/config/src/main/java/org/springframework/security/config/annotation/web/reactive/EnableWebFluxSecurity.java
+++ b/config/src/main/java/org/springframework/security/config/annotation/web/reactive/EnableWebFluxSecurity.java
@@ -82,7 +82,8 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
-@Import({ServerHttpSecurityConfiguration.class, WebFluxSecurityConfiguration.class})
+@Import({ServerHttpSecurityConfiguration.class, WebFluxSecurityConfiguration.class,
+ ReactiveOAuth2ClientImportSelector.class})
@Configuration
public @interface EnableWebFluxSecurity {
}
diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/reactive/ReactiveOAuth2ClientImportSelector.java b/config/src/main/java/org/springframework/security/config/annotation/web/reactive/ReactiveOAuth2ClientImportSelector.java
new file mode 100644
index 0000000000..c5d2ddb6da
--- /dev/null
+++ b/config/src/main/java/org/springframework/security/config/annotation/web/reactive/ReactiveOAuth2ClientImportSelector.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2002-2018 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.security.config.annotation.web.reactive;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.ImportSelector;
+import org.springframework.core.type.AnnotationMetadata;
+import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientService;
+import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository;
+import org.springframework.security.oauth2.client.web.reactive.result.method.annotation.OAuth2ClientArgumentResolver;
+import org.springframework.util.ClassUtils;
+import org.springframework.web.reactive.config.WebFluxConfigurer;
+import org.springframework.web.reactive.result.method.annotation.ArgumentResolverConfigurer;
+
+/**
+ * {@link Configuration} for OAuth 2.0 Client support.
+ *
+ *
+ * This {@code Configuration} is imported by {@link EnableWebFluxSecurity}
+ *
+ * @author Rob Winch
+ * @since 5.1
+ */
+final class ReactiveOAuth2ClientImportSelector implements ImportSelector {
+
+ @Override
+ public String[] selectImports(AnnotationMetadata importingClassMetadata) {
+ boolean oauth2ClientPresent = ClassUtils.isPresent(
+ "org.springframework.security.oauth2.client.registration.ClientRegistration", getClass().getClassLoader());
+
+ return oauth2ClientPresent ?
+ new String[] { "org.springframework.security.config.annotation.web.reactive.ReactiveOAuth2ClientImportSelector$OAuth2ClientWebFluxSecurityConfiguration" } :
+ new String[] {};
+ }
+
+ @Configuration
+ static class OAuth2ClientWebFluxSecurityConfiguration implements WebFluxConfigurer {
+ private ReactiveClientRegistrationRepository clientRegistrationRepository;
+
+ private ReactiveOAuth2AuthorizedClientService authorizedClientService;
+
+ @Override
+ public void configureArgumentResolvers(ArgumentResolverConfigurer configurer) {
+ if (this.clientRegistrationRepository != null && this.authorizedClientService != null) {
+ configurer.addCustomResolver(new OAuth2ClientArgumentResolver(this.clientRegistrationRepository, this.authorizedClientService));
+ }
+ }
+
+ @Autowired(required = false)
+ public void setClientRegistrationRepository(List clientRegistrationRepository) {
+ if (clientRegistrationRepository.size() == 1) {
+ this.clientRegistrationRepository = clientRegistrationRepository.get(0);
+ }
+ }
+
+ @Autowired(required = false)
+ public void setAuthorizedClientService(List authorizedClientService) {
+ if (authorizedClientService.size() == 1) {
+ this.authorizedClientService = authorizedClientService.get(0);
+ }
+ }
+ }
+}
diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/reactive/ServerHttpSecurityConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/web/reactive/ServerHttpSecurityConfiguration.java
index 357b43372e..8e06990092 100644
--- a/config/src/main/java/org/springframework/security/config/annotation/web/reactive/ServerHttpSecurityConfiguration.java
+++ b/config/src/main/java/org/springframework/security/config/annotation/web/reactive/ServerHttpSecurityConfiguration.java
@@ -16,8 +16,11 @@
package org.springframework.security.config.annotation.web.reactive;
+import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Scope;
import org.springframework.context.expression.BeanFactoryResolver;
@@ -31,8 +34,6 @@ import org.springframework.security.web.reactive.result.method.annotation.Authen
import org.springframework.web.reactive.config.WebFluxConfigurer;
import org.springframework.web.reactive.result.method.annotation.ArgumentResolverConfigurer;
-import static org.springframework.security.config.web.server.ServerHttpSecurity.http;
-
/**
* @author Rob Winch
* @since 5.0
@@ -74,7 +75,8 @@ class ServerHttpSecurityConfiguration implements WebFluxConfigurer {
@Bean(HTTPSECURITY_BEAN_NAME)
@Scope("prototype")
public ServerHttpSecurity httpSecurity() {
- return http()
+ ContextAwareServerHttpSecurity http = new ContextAwareServerHttpSecurity();
+ return http
.authenticationManager(authenticationManager())
.headers().and()
.logout().and();
@@ -94,4 +96,13 @@ class ServerHttpSecurityConfiguration implements WebFluxConfigurer {
}
return null;
}
+
+ private static class ContextAwareServerHttpSecurity extends ServerHttpSecurity implements
+ ApplicationContextAware {
+ @Override
+ public void setApplicationContext(ApplicationContext applicationContext)
+ throws BeansException {
+ super.setApplicationContext(applicationContext);
+ }
+ }
}
diff --git a/config/src/main/java/org/springframework/security/config/annotation/web/reactive/WebFluxSecurityConfiguration.java b/config/src/main/java/org/springframework/security/config/annotation/web/reactive/WebFluxSecurityConfiguration.java
index e353582ee6..bed91d4f97 100644
--- a/config/src/main/java/org/springframework/security/config/annotation/web/reactive/WebFluxSecurityConfiguration.java
+++ b/config/src/main/java/org/springframework/security/config/annotation/web/reactive/WebFluxSecurityConfiguration.java
@@ -16,6 +16,9 @@
package org.springframework.security.config.annotation.web.reactive;
+import java.util.Arrays;
+import java.util.List;
+
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
@@ -25,12 +28,10 @@ import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.web.reactive.result.view.CsrfRequestDataValueProcessor;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.security.web.server.WebFilterChainProxy;
+import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.reactive.result.view.AbstractView;
-import java.util.Arrays;
-import java.util.List;
-
/**
* @author Rob Winch
* @since 5.0
@@ -43,6 +44,11 @@ class WebFluxSecurityConfiguration {
private static final String SPRING_SECURITY_WEBFILTERCHAINFILTER_BEAN_NAME = BEAN_NAME_PREFIX + "WebFilterChainFilter";
+ public static final String REACTIVE_CLIENT_REGISTRATION_REPOSITORY_CLASSNAME = "org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository";
+
+ private static final boolean isOAuth2Present = ClassUtils.isPresent(
+ REACTIVE_CLIENT_REGISTRATION_REPOSITORY_CLASSNAME, WebFluxSecurityConfiguration.class.getClassLoader());
+
@Autowired(required = false)
private List securityWebFilterChains;
@@ -85,6 +91,22 @@ class WebFluxSecurityConfiguration {
.and()
.httpBasic().and()
.formLogin();
- return http.build();
+
+ if (isOAuth2Present) {
+ OAuth2ClasspathGuard.configure(this.context, http);
+ }
+
+ SecurityWebFilterChain result = http.build();
+ return result;
+ }
+
+ private static class OAuth2ClasspathGuard {
+ static void configure(ApplicationContext context, ServerHttpSecurity http) {
+ ClassLoader loader = context.getClassLoader();
+ Class> reactiveClientRegistrationRepositoryClass = ClassUtils.resolveClassName(REACTIVE_CLIENT_REGISTRATION_REPOSITORY_CLASSNAME, loader);
+ if (context.getBeanNamesForType(reactiveClientRegistrationRepositoryClass).length == 1) {
+ http.oauth2Login();
+ }
+ }
}
}
diff --git a/config/src/main/java/org/springframework/security/config/web/server/ServerHttpSecurity.java b/config/src/main/java/org/springframework/security/config/web/server/ServerHttpSecurity.java
index de8bd44274..6c8c40622c 100644
--- a/config/src/main/java/org/springframework/security/config/web/server/ServerHttpSecurity.java
+++ b/config/src/main/java/org/springframework/security/config/web/server/ServerHttpSecurity.java
@@ -24,9 +24,14 @@ import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
import org.springframework.core.Ordered;
+import org.springframework.core.ResolvableType;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
@@ -35,12 +40,23 @@ import org.springframework.security.authorization.AuthenticatedReactiveAuthoriza
import org.springframework.security.authorization.AuthorityReactiveAuthorizationManager;
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.authorization.ReactiveAuthorizationManager;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientService;
+import org.springframework.security.oauth2.client.authentication.OAuth2LoginReactiveAuthenticationManager;
+import org.springframework.security.oauth2.client.endpoint.NimbusReactiveAuthorizationCodeTokenResponseClient;
+import org.springframework.security.oauth2.client.registration.ClientRegistration;
+import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository;
+import org.springframework.security.oauth2.client.userinfo.DefaultReactiveOAuth2UserService;
+import org.springframework.security.oauth2.client.userinfo.ReactiveOAuth2UserService;
+import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectWebFilter;
+import org.springframework.security.oauth2.client.web.ServerOAuth2LoginAuthenticationTokenConverter;
import org.springframework.security.web.server.DelegatingServerAuthenticationEntryPoint;
import org.springframework.security.web.server.MatcherSecurityWebFilterChain;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.security.web.server.ServerAuthenticationEntryPoint;
import org.springframework.security.web.server.ServerFormLoginAuthenticationConverter;
import org.springframework.security.web.server.ServerHttpBasicAuthenticationConverter;
+import org.springframework.security.web.server.WebFilterExchange;
import org.springframework.security.web.server.authentication.AuthenticationWebFilter;
import org.springframework.security.web.server.authentication.HttpBasicServerAuthenticationEntryPoint;
import org.springframework.security.web.server.authentication.RedirectServerAuthenticationEntryPoint;
@@ -79,6 +95,7 @@ import org.springframework.security.web.server.savedrequest.WebSessionServerRequ
import org.springframework.security.web.server.ui.LoginPageGeneratingWebFilter;
import org.springframework.security.web.server.ui.LogoutPageGeneratingWebFilter;
import org.springframework.security.web.server.util.matcher.MediaTypeServerWebExchangeMatcher;
+import org.springframework.security.web.server.util.matcher.PathPatternParserServerWebExchangeMatcher;
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher;
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcherEntry;
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatchers;
@@ -161,6 +178,8 @@ public class ServerHttpSecurity {
private FormLoginSpec formLogin;
+ private OAuth2LoginSpec oauth2Login;
+
private LogoutSpec logout = new LogoutSpec();
private ReactiveAuthenticationManager authenticationManager;
@@ -175,6 +194,8 @@ public class ServerHttpSecurity {
private List webFilters = new ArrayList<>();
+ private ApplicationContext context;
+
private Throwable built;
/**
@@ -318,6 +339,90 @@ public class ServerHttpSecurity {
return this.formLogin;
}
+ public OAuth2LoginSpec oauth2Login() {
+ if (this.oauth2Login == null) {
+ this.oauth2Login = new OAuth2LoginSpec();
+ }
+ return this.oauth2Login;
+ }
+
+ public class OAuth2LoginSpec {
+ private ReactiveClientRegistrationRepository clientRegistrationRepository;
+
+ private ReactiveOAuth2AuthorizedClientService authorizedClientService;
+
+ public OAuth2LoginSpec clientRegistrationRepository(ReactiveClientRegistrationRepository clientRegistrationRepository) {
+ this.clientRegistrationRepository = clientRegistrationRepository;
+ return this;
+ }
+
+ public OAuth2LoginSpec authorizedClientService(ReactiveOAuth2AuthorizedClientService authorizedClientService) {
+ this.authorizedClientService = authorizedClientService;
+ return this;
+ }
+
+ protected void configure(LoginPageGeneratingWebFilter loginPageFilter, ServerHttpSecurity http) {
+ if (loginPageFilter != null) {
+ loginPageFilter.setOauth2AuthenticationUrlToClientName(getLinks());
+ }
+
+ ReactiveClientRegistrationRepository clientRegistrationRepository = getClientRegistrationRepository();
+ ReactiveOAuth2AuthorizedClientService authorizedClientService = getAuthorizedClientService();
+ OAuth2AuthorizationRequestRedirectWebFilter oauthRedirectFilter = new OAuth2AuthorizationRequestRedirectWebFilter(clientRegistrationRepository);
+
+ NimbusReactiveAuthorizationCodeTokenResponseClient client = new NimbusReactiveAuthorizationCodeTokenResponseClient();
+ ReactiveOAuth2UserService userService = new DefaultReactiveOAuth2UserService();
+ OAuth2LoginReactiveAuthenticationManager manager = new OAuth2LoginReactiveAuthenticationManager(client, userService,
+ authorizedClientService);
+ AuthenticationWebFilter authenticationFilter = new AuthenticationWebFilter(manager);
+ authenticationFilter.setRequiresAuthenticationMatcher(new PathPatternParserServerWebExchangeMatcher("/login/oauth2/code/{registrationId}"));
+ authenticationFilter.setAuthenticationConverter(new ServerOAuth2LoginAuthenticationTokenConverter(clientRegistrationRepository));
+
+ RedirectServerAuthenticationSuccessHandler redirectHandler = new RedirectServerAuthenticationSuccessHandler();
+
+ authenticationFilter.setAuthenticationSuccessHandler(redirectHandler);
+ authenticationFilter.setAuthenticationFailureHandler(new ServerAuthenticationFailureHandler() {
+ @Override
+ public Mono onAuthenticationFailure(WebFilterExchange webFilterExchange,
+ AuthenticationException exception) {
+ return Mono.error(exception);
+ }
+ });
+ authenticationFilter.setSecurityContextRepository(new WebSessionServerSecurityContextRepository());
+
+ http.addFilterAt(oauthRedirectFilter, SecurityWebFiltersOrder.HTTP_BASIC);
+ http.addFilterAt(authenticationFilter, SecurityWebFiltersOrder.AUTHENTICATION);
+ }
+
+ private Map getLinks() {
+ Iterable registrations = getBeanOrNull(ResolvableType.forClassWithGenerics(Iterable.class, ClientRegistration.class));
+ if (registrations == null) {
+ return Collections.emptyMap();
+ }
+ Map result = new HashMap<>();
+ registrations.iterator().forEachRemaining(r -> {
+ result.put("/oauth2/authorization/" + r.getRegistrationId(), r.getClientName());
+ });
+ return result;
+ }
+
+ private ReactiveClientRegistrationRepository getClientRegistrationRepository() {
+ if (this.clientRegistrationRepository == null) {
+ this.clientRegistrationRepository = getBeanOrNull(ReactiveClientRegistrationRepository.class);
+ }
+ return this.clientRegistrationRepository;
+ }
+
+ private ReactiveOAuth2AuthorizedClientService getAuthorizedClientService() {
+ if (this.authorizedClientService == null) {
+ this.authorizedClientService = getBeanOrNull(ReactiveOAuth2AuthorizedClientService.class);
+ }
+ return this.authorizedClientService;
+ }
+
+ private OAuth2LoginSpec() {}
+ }
+
/**
* Configures HTTP Response Headers. The default headers are:
*
@@ -505,17 +610,22 @@ public class ServerHttpSecurity {
this.httpBasic.authenticationManager(this.authenticationManager);
this.httpBasic.configure(this);
}
+ LoginPageGeneratingWebFilter loginPageFilter = null;
if(this.formLogin != null) {
this.formLogin.authenticationManager(this.authenticationManager);
if(this.securityContextRepository != null) {
this.formLogin.securityContextRepository(this.securityContextRepository);
}
if(this.formLogin.authenticationEntryPoint == null) {
- this.webFilters.add(new OrderedWebFilter(new LoginPageGeneratingWebFilter(), SecurityWebFiltersOrder.LOGIN_PAGE_GENERATING.getOrder()));
+ loginPageFilter = new LoginPageGeneratingWebFilter();
+ this.webFilters.add(new OrderedWebFilter(loginPageFilter, SecurityWebFiltersOrder.LOGIN_PAGE_GENERATING.getOrder()));
this.webFilters.add(new OrderedWebFilter(new LogoutPageGeneratingWebFilter(), SecurityWebFiltersOrder.LOGOUT_PAGE_GENERATING.getOrder()));
}
this.formLogin.configure(this);
}
+ if (this.oauth2Login != null) {
+ this.oauth2Login.configure(loginPageFilter, this);
+ }
if(this.logout != null) {
this.logout.configure(this);
}
@@ -589,7 +699,7 @@ public class ServerHttpSecurity {
return new OrderedWebFilter(result, SecurityWebFiltersOrder.REACTOR_CONTEXT.getOrder());
}
- private ServerHttpSecurity() {}
+ protected ServerHttpSecurity() {}
/**
* Configures authorization
@@ -1402,6 +1512,27 @@ public class ServerHttpSecurity {
private LogoutSpec() {}
}
+ private T getBeanOrNull(Class beanClass) {
+ return getBeanOrNull(ResolvableType.forClass(beanClass));
+ }
+
+
+ private T getBeanOrNull(ResolvableType type) {
+ if (this.context == null) {
+ return null;
+ }
+ String[] names = this.context.getBeanNamesForType(type);
+ if (names.length == 1) {
+ return (T) this.context.getBean(names[0]);
+ }
+ return null;
+ }
+
+ protected void setApplicationContext(ApplicationContext applicationContext)
+ throws BeansException {
+ this.context = applicationContext;
+ }
+
private static class OrderedWebFilter implements WebFilter, Ordered {
private final WebFilter webFilter;
private final int order;
diff --git a/oauth2/oauth2-client/spring-security-oauth2-client.gradle b/oauth2/oauth2-client/spring-security-oauth2-client.gradle
index f1f3966bb3..94f29ae607 100644
--- a/oauth2/oauth2-client/spring-security-oauth2-client.gradle
+++ b/oauth2/oauth2-client/spring-security-oauth2-client.gradle
@@ -8,10 +8,14 @@ dependencies {
compile 'com.nimbusds:oauth2-oidc-sdk'
optional project(':spring-security-oauth2-jose')
+ optional 'io.projectreactor:reactor-core'
+ optional 'org.springframework:spring-webflux'
testCompile powerMock2Dependencies
testCompile 'com.squareup.okhttp3:mockwebserver'
testCompile 'com.fasterxml.jackson.core:jackson-databind'
+ testCompile 'io.projectreactor.ipc:reactor-netty'
+ testCompile 'io.projectreactor:reactor-test'
provided 'javax.servlet:javax.servlet-api'
}
diff --git a/web/src/main/java/org/springframework/security/web/server/ui/LoginPageGeneratingWebFilter.java b/web/src/main/java/org/springframework/security/web/server/ui/LoginPageGeneratingWebFilter.java
index 6be4f8bbca..373ee21e4b 100644
--- a/web/src/main/java/org/springframework/security/web/server/ui/LoginPageGeneratingWebFilter.java
+++ b/web/src/main/java/org/springframework/security/web/server/ui/LoginPageGeneratingWebFilter.java
@@ -16,6 +16,10 @@
package org.springframework.security.web.server.ui;
+import java.nio.charset.Charset;
+import java.util.HashMap;
+import java.util.Map;
+
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.http.HttpMethod;
@@ -25,13 +29,14 @@ import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.security.web.server.csrf.CsrfToken;
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher;
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatchers;
+import org.springframework.util.Assert;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
-import reactor.core.publisher.Mono;
+import org.springframework.web.util.HtmlUtils;
-import java.nio.charset.Charset;
+import reactor.core.publisher.Mono;
/**
* Generates a default log in page used for authenticating users.
@@ -43,6 +48,14 @@ public class LoginPageGeneratingWebFilter implements WebFilter {
private ServerWebExchangeMatcher matcher = ServerWebExchangeMatchers
.pathMatchers(HttpMethod.GET, "/login");
+ private Map oauth2AuthenticationUrlToClientName = new HashMap<>();
+
+ public void setOauth2AuthenticationUrlToClientName(
+ Map oauth2AuthenticationUrlToClientName) {
+ Assert.notNull(oauth2AuthenticationUrlToClientName, "oauth2AuthenticationUrlToClientName cannot be null");
+ this.oauth2AuthenticationUrlToClientName = oauth2AuthenticationUrlToClientName;
+ }
+
@Override
public Mono filter(ServerWebExchange exchange, WebFilterChain chain) {
return this.matcher.matches(exchange)
@@ -59,22 +72,24 @@ public class LoginPageGeneratingWebFilter implements WebFilter {
}
private Mono createBuffer(ServerWebExchange exchange) {
- MultiValueMap queryParams = exchange.getRequest()
- .getQueryParams();
+
Mono token = exchange.getAttributeOrDefault(CsrfToken.class.getName(), Mono.empty());
return token
.map(LoginPageGeneratingWebFilter::csrfToken)
.defaultIfEmpty("")
.map(csrfTokenHtmlInput -> {
- boolean isError = queryParams.containsKey("error");
- boolean isLogoutSuccess = queryParams.containsKey("logout");
- byte[] bytes = createPage(isError, isLogoutSuccess, csrfTokenHtmlInput);
+ byte[] bytes = createPage(exchange, csrfTokenHtmlInput);
DataBufferFactory bufferFactory = exchange.getResponse().bufferFactory();
return bufferFactory.wrap(bytes);
});
}
- private static byte[] createPage(boolean isError, boolean isLogoutSuccess, String csrfTokenHtmlInput) {
+ private byte[] createPage(ServerWebExchange exchange, String csrfTokenHtmlInput) {
+ MultiValueMap queryParams = exchange.getRequest()
+ .getQueryParams();
+ boolean isError = queryParams.containsKey("error");
+ boolean isLogoutSuccess = queryParams.containsKey("logout");
+ String contextPath = exchange.getRequest().getPath().contextPath().value();
String page = "\n"
+ "\n"
+ " \n"
@@ -103,6 +118,7 @@ public class LoginPageGeneratingWebFilter implements WebFilter {
+ csrfTokenHtmlInput
+ " Sign in \n"
+ " \n"
+ + oauth2LoginLinks(contextPath, this.oauth2AuthenticationUrlToClientName)
+ " \n"
+ " \n"
+ "";
@@ -110,6 +126,26 @@ public class LoginPageGeneratingWebFilter implements WebFilter {
return page.getBytes(Charset.defaultCharset());
}
+ private static String oauth2LoginLinks(String contextPath, Map oauth2AuthenticationUrlToClientName) {
+ if (oauth2AuthenticationUrlToClientName.isEmpty()) {
+ return "";
+ }
+ StringBuilder sb = new StringBuilder();
+ sb.append("\n");
+ return sb.toString();
+ }
+
private static String csrfToken(CsrfToken token) {
return " \n";
}