Allow form login when single OAuth2 Provider is configured

Closes gh-6802
This commit is contained in:
Steve Riesenberg 2021-05-27 12:33:49 -05:00
parent 812bb0ead0
commit 79c2b8709b
No known key found for this signature in database
GPG Key ID: 5F311AB48A55D521
2 changed files with 52 additions and 4 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2022 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.
@ -16,6 +16,7 @@
package org.springframework.security.config.annotation.web.configurers.oauth2.client;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@ -73,12 +74,14 @@ import org.springframework.security.web.authentication.ui.DefaultLoginPageGenera
import org.springframework.security.web.savedrequest.RequestCache;
import org.springframework.security.web.util.matcher.AndRequestMatcher;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
import org.springframework.security.web.util.matcher.NegatedRequestMatcher;
import org.springframework.security.web.util.matcher.OrRequestMatcher;
import org.springframework.security.web.util.matcher.RequestHeaderRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
/**
* An {@link AbstractHttpConfigurer} for OAuth 2.0 Login, which leverages the OAuth 2.0
@ -503,14 +506,28 @@ public final class OAuth2LoginConfigurer<B extends HttpSecurityBuilder<B>>
new OrRequestMatcher(loginPageMatcher, faviconMatcher), defaultEntryPointMatcher);
RequestMatcher notXRequestedWith = new NegatedRequestMatcher(
new RequestHeaderRequestMatcher("X-Requested-With", "XMLHttpRequest"));
RequestMatcher formLoginNotEnabled = getFormLoginNotEnabledRequestMatcher(http);
LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> entryPoints = new LinkedHashMap<>();
entryPoints.put(new AndRequestMatcher(notXRequestedWith, new NegatedRequestMatcher(defaultLoginPageMatcher)),
new LoginUrlAuthenticationEntryPoint(providerLoginPage));
entryPoints.put(new AndRequestMatcher(notXRequestedWith, new NegatedRequestMatcher(defaultLoginPageMatcher),
formLoginNotEnabled), new LoginUrlAuthenticationEntryPoint(providerLoginPage));
DelegatingAuthenticationEntryPoint loginEntryPoint = new DelegatingAuthenticationEntryPoint(entryPoints);
loginEntryPoint.setDefaultEntryPoint(this.getAuthenticationEntryPoint());
return loginEntryPoint;
}
private RequestMatcher getFormLoginNotEnabledRequestMatcher(B http) {
DefaultLoginPageGeneratingFilter defaultLoginPageGeneratingFilter = http
.getSharedObject(DefaultLoginPageGeneratingFilter.class);
Field formLoginEnabledField = (defaultLoginPageGeneratingFilter != null)
? ReflectionUtils.findField(DefaultLoginPageGeneratingFilter.class, "formLoginEnabled") : null;
if (formLoginEnabledField != null) {
ReflectionUtils.makeAccessible(formLoginEnabledField);
return (request) -> Boolean.FALSE
.equals(ReflectionUtils.getField(formLoginEnabledField, defaultLoginPageGeneratingFilter));
}
return AnyRequestMatcher.INSTANCE;
}
/**
* Configuration options for the Authorization Server's Authorization Endpoint.
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2022 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.
@ -368,6 +368,17 @@ public class OAuth2LoginConfigurerTests {
assertThat(this.response.getRedirectedUrl()).matches("http://localhost/oauth2/authorization/google");
}
// gh-6802
@Test
public void oauth2LoginWithOneClientConfiguredAndFormLoginThenRedirectDefaultLoginPage() throws Exception {
loadConfig(OAuth2LoginConfigFormLogin.class);
String requestUri = "/";
this.request = new MockHttpServletRequest("GET", requestUri);
this.request.setServletPath(requestUri);
this.springSecurityFilterChain.doFilter(this.request, this.response, this.filterChain);
assertThat(this.response.getRedirectedUrl()).matches("http://localhost/login");
}
// gh-5347
@Test
public void oauth2LoginWithOneClientConfiguredAndRequestFaviconNotAuthenticatedThenRedirectDefaultLoginPage()
@ -642,6 +653,26 @@ public class OAuth2LoginConfigurerTests {
}
@EnableWebSecurity
static class OAuth2LoginConfigFormLogin extends CommonWebSecurityConfigurerAdapter {
private final InMemoryClientRegistrationRepository clientRegistrationRepository = new InMemoryClientRegistrationRepository(
GOOGLE_CLIENT_REGISTRATION);
@Override
protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
.oauth2Login()
.clientRegistrationRepository(this.clientRegistrationRepository)
.and()
.formLogin();
// @formatter:on
super.configure(http);
}
}
@EnableWebSecurity
static class OAuth2LoginInLambdaConfig extends CommonLambdaWebSecurityConfigurerAdapter
implements ApplicationListener<AuthenticationSuccessEvent> {