Skip to content

Commit 4e88cb8

Browse files
author
Steve Riesenberg
committed
Allow form login when single OAuth2 Provider is configured
Closes spring-projectsgh-6802
1 parent d182916 commit 4e88cb8

File tree

2 files changed

+52
-4
lines changed

2 files changed

+52
-4
lines changed

config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurer.java

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2021 the original author or authors.
2+
* Copyright 2002-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,6 +16,7 @@
1616

1717
package org.springframework.security.config.annotation.web.configurers.oauth2.client;
1818

19+
import java.lang.reflect.Field;
1920
import java.util.ArrayList;
2021
import java.util.Collections;
2122
import java.util.HashMap;
@@ -73,12 +74,14 @@
7374
import org.springframework.security.web.savedrequest.RequestCache;
7475
import org.springframework.security.web.util.matcher.AndRequestMatcher;
7576
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
77+
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
7678
import org.springframework.security.web.util.matcher.NegatedRequestMatcher;
7779
import org.springframework.security.web.util.matcher.OrRequestMatcher;
7880
import org.springframework.security.web.util.matcher.RequestHeaderRequestMatcher;
7981
import org.springframework.security.web.util.matcher.RequestMatcher;
8082
import org.springframework.util.Assert;
8183
import org.springframework.util.ClassUtils;
84+
import org.springframework.util.ReflectionUtils;
8285

8386
/**
8487
* An {@link AbstractHttpConfigurer} for OAuth 2.0 Login, which leverages the OAuth 2.0
@@ -503,14 +506,28 @@ private AuthenticationEntryPoint getLoginEntryPoint(B http, String providerLogin
503506
new OrRequestMatcher(loginPageMatcher, faviconMatcher), defaultEntryPointMatcher);
504507
RequestMatcher notXRequestedWith = new NegatedRequestMatcher(
505508
new RequestHeaderRequestMatcher("X-Requested-With", "XMLHttpRequest"));
509+
RequestMatcher formLoginNotEnabled = getFormLoginNotEnabledRequestMatcher(http);
506510
LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> entryPoints = new LinkedHashMap<>();
507-
entryPoints.put(new AndRequestMatcher(notXRequestedWith, new NegatedRequestMatcher(defaultLoginPageMatcher)),
508-
new LoginUrlAuthenticationEntryPoint(providerLoginPage));
511+
entryPoints.put(new AndRequestMatcher(notXRequestedWith, new NegatedRequestMatcher(defaultLoginPageMatcher),
512+
formLoginNotEnabled), new LoginUrlAuthenticationEntryPoint(providerLoginPage));
509513
DelegatingAuthenticationEntryPoint loginEntryPoint = new DelegatingAuthenticationEntryPoint(entryPoints);
510514
loginEntryPoint.setDefaultEntryPoint(this.getAuthenticationEntryPoint());
511515
return loginEntryPoint;
512516
}
513517

518+
private RequestMatcher getFormLoginNotEnabledRequestMatcher(B http) {
519+
DefaultLoginPageGeneratingFilter defaultLoginPageGeneratingFilter = http
520+
.getSharedObject(DefaultLoginPageGeneratingFilter.class);
521+
Field formLoginEnabledField = (defaultLoginPageGeneratingFilter != null)
522+
? ReflectionUtils.findField(DefaultLoginPageGeneratingFilter.class, "formLoginEnabled") : null;
523+
if (formLoginEnabledField != null) {
524+
ReflectionUtils.makeAccessible(formLoginEnabledField);
525+
return (request) -> Boolean.FALSE
526+
.equals(ReflectionUtils.getField(formLoginEnabledField, defaultLoginPageGeneratingFilter));
527+
}
528+
return AnyRequestMatcher.INSTANCE;
529+
}
530+
514531
/**
515532
* Configuration options for the Authorization Server's Authorization Endpoint.
516533
*/

config/src/test/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurerTests.java

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2021 the original author or authors.
2+
* Copyright 2002-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -368,6 +368,17 @@ public void oauth2LoginWithOneClientConfiguredThenRedirectForAuthorization() thr
368368
assertThat(this.response.getRedirectedUrl()).matches("http://localhost/oauth2/authorization/google");
369369
}
370370

371+
// gh-6802
372+
@Test
373+
public void oauth2LoginWithOneClientConfiguredAndFormLoginThenRedirectDefaultLoginPage() throws Exception {
374+
loadConfig(OAuth2LoginConfigFormLogin.class);
375+
String requestUri = "/";
376+
this.request = new MockHttpServletRequest("GET", requestUri);
377+
this.request.setServletPath(requestUri);
378+
this.springSecurityFilterChain.doFilter(this.request, this.response, this.filterChain);
379+
assertThat(this.response.getRedirectedUrl()).matches("http://localhost/login");
380+
}
381+
371382
// gh-5347
372383
@Test
373384
public void oauth2LoginWithOneClientConfiguredAndRequestFaviconNotAuthenticatedThenRedirectDefaultLoginPage()
@@ -642,6 +653,26 @@ public void onApplicationEvent(AuthenticationSuccessEvent event) {
642653

643654
}
644655

656+
@EnableWebSecurity
657+
static class OAuth2LoginConfigFormLogin extends CommonWebSecurityConfigurerAdapter {
658+
659+
private final InMemoryClientRegistrationRepository clientRegistrationRepository = new InMemoryClientRegistrationRepository(
660+
GOOGLE_CLIENT_REGISTRATION);
661+
662+
@Override
663+
protected void configure(HttpSecurity http) throws Exception {
664+
// @formatter:off
665+
http
666+
.oauth2Login()
667+
.clientRegistrationRepository(this.clientRegistrationRepository)
668+
.and()
669+
.formLogin();
670+
// @formatter:on
671+
super.configure(http);
672+
}
673+
674+
}
675+
645676
@EnableWebSecurity
646677
static class OAuth2LoginInLambdaConfig extends CommonLambdaWebSecurityConfigurerAdapter
647678
implements ApplicationListener<AuthenticationSuccessEvent> {

0 commit comments

Comments
 (0)