mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-07-04 09:42:29 +00:00
oauth2Login WebFlux does not auto-redirect for XHR request
Fixes gh-8118
This commit is contained in:
parent
98bd1a3f60
commit
4706b16a2b
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2019 the original author or authors.
|
* Copyright 2002-2020 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -1181,24 +1181,56 @@ public class ServerHttpSecurity {
|
|||||||
authenticationFilter.setAuthenticationFailureHandler(getAuthenticationFailureHandler());
|
authenticationFilter.setAuthenticationFailureHandler(getAuthenticationFailureHandler());
|
||||||
authenticationFilter.setSecurityContextRepository(this.securityContextRepository);
|
authenticationFilter.setSecurityContextRepository(this.securityContextRepository);
|
||||||
|
|
||||||
MediaTypeServerWebExchangeMatcher htmlMatcher = new MediaTypeServerWebExchangeMatcher(
|
setDefaultEntryPoints(http);
|
||||||
MediaType.TEXT_HTML);
|
|
||||||
htmlMatcher.setIgnoredMediaTypes(Collections.singleton(MediaType.ALL));
|
|
||||||
Map<String, String> urlToText = http.oauth2Login.getLinks();
|
|
||||||
String authenticationEntryPointRedirectPath;
|
|
||||||
if (urlToText.size() == 1) {
|
|
||||||
authenticationEntryPointRedirectPath = urlToText.keySet().iterator().next();
|
|
||||||
} else {
|
|
||||||
authenticationEntryPointRedirectPath = "/login";
|
|
||||||
}
|
|
||||||
RedirectServerAuthenticationEntryPoint entryPoint = new RedirectServerAuthenticationEntryPoint(authenticationEntryPointRedirectPath);
|
|
||||||
entryPoint.setRequestCache(http.requestCache.requestCache);
|
|
||||||
http.defaultEntryPoints.add(new DelegateEntry(htmlMatcher, entryPoint));
|
|
||||||
|
|
||||||
http.addFilterAt(oauthRedirectFilter, SecurityWebFiltersOrder.HTTP_BASIC);
|
http.addFilterAt(oauthRedirectFilter, SecurityWebFiltersOrder.HTTP_BASIC);
|
||||||
http.addFilterAt(authenticationFilter, SecurityWebFiltersOrder.AUTHENTICATION);
|
http.addFilterAt(authenticationFilter, SecurityWebFiltersOrder.AUTHENTICATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setDefaultEntryPoints(ServerHttpSecurity http) {
|
||||||
|
String defaultLoginPage = "/login";
|
||||||
|
Map<String, String> urlToText = http.oauth2Login.getLinks();
|
||||||
|
String providerLoginPage = null;
|
||||||
|
if (urlToText.size() == 1) {
|
||||||
|
providerLoginPage = urlToText.keySet().iterator().next();
|
||||||
|
}
|
||||||
|
|
||||||
|
MediaTypeServerWebExchangeMatcher htmlMatcher = new MediaTypeServerWebExchangeMatcher(
|
||||||
|
MediaType.APPLICATION_XHTML_XML, new MediaType("image", "*"),
|
||||||
|
MediaType.TEXT_HTML, MediaType.TEXT_PLAIN);
|
||||||
|
htmlMatcher.setIgnoredMediaTypes(Collections.singleton(MediaType.ALL));
|
||||||
|
|
||||||
|
ServerWebExchangeMatcher xhrMatcher = exchange -> {
|
||||||
|
if (exchange.getRequest().getHeaders().getOrEmpty("X-Requested-With").contains("XMLHttpRequest")) {
|
||||||
|
return ServerWebExchangeMatcher.MatchResult.match();
|
||||||
|
}
|
||||||
|
return ServerWebExchangeMatcher.MatchResult.notMatch();
|
||||||
|
};
|
||||||
|
ServerWebExchangeMatcher notXhrMatcher = new NegatedServerWebExchangeMatcher(xhrMatcher);
|
||||||
|
|
||||||
|
ServerWebExchangeMatcher defaultEntryPointMatcher = new AndServerWebExchangeMatcher(
|
||||||
|
notXhrMatcher, htmlMatcher);
|
||||||
|
|
||||||
|
if (providerLoginPage != null) {
|
||||||
|
ServerWebExchangeMatcher loginPageMatcher = new PathPatternParserServerWebExchangeMatcher(defaultLoginPage);
|
||||||
|
ServerWebExchangeMatcher faviconMatcher = new PathPatternParserServerWebExchangeMatcher("/favicon.ico");
|
||||||
|
ServerWebExchangeMatcher defaultLoginPageMatcher = new AndServerWebExchangeMatcher(
|
||||||
|
new OrServerWebExchangeMatcher(loginPageMatcher, faviconMatcher), defaultEntryPointMatcher);
|
||||||
|
|
||||||
|
ServerWebExchangeMatcher matcher = new AndServerWebExchangeMatcher(
|
||||||
|
notXhrMatcher, new NegatedServerWebExchangeMatcher(defaultLoginPageMatcher));
|
||||||
|
RedirectServerAuthenticationEntryPoint entryPoint =
|
||||||
|
new RedirectServerAuthenticationEntryPoint(providerLoginPage);
|
||||||
|
entryPoint.setRequestCache(http.requestCache.requestCache);
|
||||||
|
http.defaultEntryPoints.add(new DelegateEntry(matcher, entryPoint));
|
||||||
|
}
|
||||||
|
|
||||||
|
RedirectServerAuthenticationEntryPoint defaultEntryPoint =
|
||||||
|
new RedirectServerAuthenticationEntryPoint(defaultLoginPage);
|
||||||
|
defaultEntryPoint.setRequestCache(http.requestCache.requestCache);
|
||||||
|
http.defaultEntryPoints.add(new DelegateEntry(defaultEntryPointMatcher, defaultEntryPoint));
|
||||||
|
}
|
||||||
|
|
||||||
private ServerAuthenticationSuccessHandler getAuthenticationSuccessHandler(ServerHttpSecurity http) {
|
private ServerAuthenticationSuccessHandler getAuthenticationSuccessHandler(ServerHttpSecurity http) {
|
||||||
if (this.authenticationSuccessHandler == null) {
|
if (this.authenticationSuccessHandler == null) {
|
||||||
RedirectServerAuthenticationSuccessHandler handler = new RedirectServerAuthenticationSuccessHandler();
|
RedirectServerAuthenticationSuccessHandler handler = new RedirectServerAuthenticationSuccessHandler();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2019 the original author or authors.
|
* Copyright 2002-2020 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -24,6 +24,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.security.authentication.ReactiveAuthenticationManager;
|
import org.springframework.security.authentication.ReactiveAuthenticationManager;
|
||||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||||
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
|
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
|
||||||
@ -185,6 +186,22 @@ public class OAuth2LoginTests {
|
|||||||
assertThat(driver.getCurrentUrl()).startsWith("https://github.com/login/oauth/authorize");
|
assertThat(driver.getCurrentUrl()).startsWith("https://github.com/login/oauth/authorize");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// gh-8118
|
||||||
|
@Test
|
||||||
|
public void defaultLoginPageWithSingleClientRegistrationAndXhrRequestThenDoesNotRedirectForAuthorization() {
|
||||||
|
this.spring.register(OAuth2LoginWithSingleClientRegistrations.class, WebFluxConfig.class).autowire();
|
||||||
|
|
||||||
|
this.client.get()
|
||||||
|
.uri("/")
|
||||||
|
.header("X-Requested-With", "XMLHttpRequest")
|
||||||
|
.exchange()
|
||||||
|
.expectStatus().is3xxRedirection()
|
||||||
|
.expectHeader().valueEquals(HttpHeaders.LOCATION, "/login");
|
||||||
|
}
|
||||||
|
|
||||||
|
@EnableWebFlux
|
||||||
|
static class WebFluxConfig { }
|
||||||
|
|
||||||
@EnableWebFluxSecurity
|
@EnableWebFluxSecurity
|
||||||
static class OAuth2LoginWithSingleClientRegistrations {
|
static class OAuth2LoginWithSingleClientRegistrations {
|
||||||
@Bean
|
@Bean
|
||||||
|
Loading…
x
Reference in New Issue
Block a user