mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-05-31 17:22:13 +00:00
Limit oauth2Login() links to redirect-based flows
This prevents the generated login page from showing links for authorization grant types like "client_credentials" which are not redirect-based, and thus not meant for interactive use in the browser. Closes gh-9457
This commit is contained in:
parent
a325216f19
commit
2b4b856b32
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2020 the original author or authors.
|
* Copyright 2002-2021 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.
|
||||||
@ -58,6 +58,7 @@ import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequest
|
|||||||
import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestResolver;
|
import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestResolver;
|
||||||
import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository;
|
import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository;
|
||||||
import org.springframework.security.oauth2.client.web.OAuth2LoginAuthenticationFilter;
|
import org.springframework.security.oauth2.client.web.OAuth2LoginAuthenticationFilter;
|
||||||
|
import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
||||||
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
|
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
|
||||||
import org.springframework.security.oauth2.core.OAuth2Error;
|
import org.springframework.security.oauth2.core.OAuth2Error;
|
||||||
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
|
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
|
||||||
@ -485,8 +486,12 @@ public final class OAuth2LoginConfigurer<B extends HttpSecurityBuilder<B>>
|
|||||||
? this.authorizationEndpointConfig.authorizationRequestBaseUri
|
? this.authorizationEndpointConfig.authorizationRequestBaseUri
|
||||||
: OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI;
|
: OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI;
|
||||||
Map<String, String> loginUrlToClientName = new HashMap<>();
|
Map<String, String> loginUrlToClientName = new HashMap<>();
|
||||||
clientRegistrations.forEach((registration) -> loginUrlToClientName.put(
|
clientRegistrations.forEach((registration) -> {
|
||||||
authorizationRequestBaseUri + "/" + registration.getRegistrationId(), registration.getClientName()));
|
if (AuthorizationGrantType.AUTHORIZATION_CODE.equals(registration.getAuthorizationGrantType())) {
|
||||||
|
String authorizationRequestUri = authorizationRequestBaseUri + "/" + registration.getRegistrationId();
|
||||||
|
loginUrlToClientName.put(authorizationRequestUri, registration.getClientName());
|
||||||
|
}
|
||||||
|
});
|
||||||
return loginUrlToClientName;
|
return loginUrlToClientName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,6 +80,7 @@ import org.springframework.security.oauth2.client.web.server.ServerOAuth2Authori
|
|||||||
import org.springframework.security.oauth2.client.web.server.ServerOAuth2AuthorizedClientRepository;
|
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.WebSessionOAuth2ServerAuthorizationRequestRepository;
|
||||||
import org.springframework.security.oauth2.client.web.server.authentication.OAuth2LoginAuthenticationWebFilter;
|
import org.springframework.security.oauth2.client.web.server.authentication.OAuth2LoginAuthenticationWebFilter;
|
||||||
|
import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
||||||
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
|
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
|
||||||
import org.springframework.security.oauth2.core.OAuth2AuthorizationException;
|
import org.springframework.security.oauth2.core.OAuth2AuthorizationException;
|
||||||
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
|
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
|
||||||
@ -3356,8 +3357,11 @@ public class ServerHttpSecurity {
|
|||||||
return Collections.emptyMap();
|
return Collections.emptyMap();
|
||||||
}
|
}
|
||||||
Map<String, String> result = new HashMap<>();
|
Map<String, String> result = new HashMap<>();
|
||||||
registrations.iterator().forEachRemaining(
|
registrations.iterator().forEachRemaining((r) -> {
|
||||||
(r) -> result.put("/oauth2/authorization/" + r.getRegistrationId(), r.getClientName()));
|
if (AuthorizationGrantType.AUTHORIZATION_CODE.equals(r.getAuthorizationGrantType())) {
|
||||||
|
result.put("/oauth2/authorization/" + r.getRegistrationId(), r.getClientName());
|
||||||
|
}
|
||||||
|
});
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2019 the original author or authors.
|
* Copyright 2002-2021 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.
|
||||||
@ -126,6 +126,11 @@ public class OAuth2LoginConfigurerTests {
|
|||||||
.build();
|
.build();
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
|
|
||||||
|
// @formatter:off
|
||||||
|
private static final ClientRegistration CLIENT_CREDENTIALS_REGISTRATION = TestClientRegistrations.clientCredentials()
|
||||||
|
.build();
|
||||||
|
// @formatter:on
|
||||||
|
|
||||||
private ConfigurableApplicationContext context;
|
private ConfigurableApplicationContext context;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
@ -396,6 +401,18 @@ public class OAuth2LoginConfigurerTests {
|
|||||||
assertThat(this.response.getRedirectedUrl()).doesNotMatch("http://localhost/oauth2/authorization/google");
|
assertThat(this.response.getRedirectedUrl()).doesNotMatch("http://localhost/oauth2/authorization/google");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// gh-9457
|
||||||
|
@Test
|
||||||
|
public void oauth2LoginWithOneAuthorizationCodeClientAndOtherClientsConfiguredThenRedirectForAuthorization()
|
||||||
|
throws Exception {
|
||||||
|
loadConfig(OAuth2LoginConfigAuthorizationCodeClientAndOtherClients.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/oauth2/authorization/google");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void oauth2LoginWithCustomLoginPageThenRedirectCustomLoginPage() throws Exception {
|
public void oauth2LoginWithCustomLoginPageThenRedirectCustomLoginPage() throws Exception {
|
||||||
loadConfig(OAuth2LoginConfigCustomLoginPage.class);
|
loadConfig(OAuth2LoginConfigCustomLoginPage.class);
|
||||||
@ -799,6 +816,23 @@ public class OAuth2LoginConfigurerTests {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@EnableWebSecurity
|
||||||
|
static class OAuth2LoginConfigAuthorizationCodeClientAndOtherClients extends CommonWebSecurityConfigurerAdapter {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure(HttpSecurity http) throws Exception {
|
||||||
|
// @formatter:off
|
||||||
|
http
|
||||||
|
.oauth2Login()
|
||||||
|
.clientRegistrationRepository(
|
||||||
|
new InMemoryClientRegistrationRepository(
|
||||||
|
GOOGLE_CLIENT_REGISTRATION, CLIENT_CREDENTIALS_REGISTRATION));
|
||||||
|
// @formatter:on
|
||||||
|
super.configure(http);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
static class OAuth2LoginConfigCustomLoginPage extends CommonWebSecurityConfigurerAdapter {
|
static class OAuth2LoginConfigCustomLoginPage extends CommonWebSecurityConfigurerAdapter {
|
||||||
|
|
||||||
|
@ -134,6 +134,11 @@ public class OAuth2LoginTests {
|
|||||||
private static ClientRegistration google = CommonOAuth2Provider.GOOGLE.getBuilder("google").clientId("client")
|
private static ClientRegistration google = CommonOAuth2Provider.GOOGLE.getBuilder("google").clientId("client")
|
||||||
.clientSecret("secret").build();
|
.clientSecret("secret").build();
|
||||||
|
|
||||||
|
// @formatter:off
|
||||||
|
private static ClientRegistration clientCredentials = TestClientRegistrations.clientCredentials()
|
||||||
|
.build();
|
||||||
|
// @formatter:on
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public void setApplicationContext(ApplicationContext context) {
|
public void setApplicationContext(ApplicationContext context) {
|
||||||
if (context.getBeanNamesForType(WebHandler.class).length > 0) {
|
if (context.getBeanNamesForType(WebHandler.class).length > 0) {
|
||||||
@ -179,6 +184,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-9457
|
||||||
|
@Test
|
||||||
|
public void defaultLoginPageWithAuthorizationCodeAndClientCredentialsClientRegistrationThenRedirect() {
|
||||||
|
this.spring.register(OAuth2LoginWithAuthorizationCodeAndClientCredentialsClientRegistration.class).autowire();
|
||||||
|
// @formatter:off
|
||||||
|
WebTestClient webTestClient = WebTestClientBuilder
|
||||||
|
.bindToWebFilters(new GitHubWebFilter(), this.springSecurity)
|
||||||
|
.build();
|
||||||
|
WebDriver driver = WebTestClientHtmlUnitDriverBuilder
|
||||||
|
.webTestClientSetup(webTestClient)
|
||||||
|
.build();
|
||||||
|
// @formatter:on
|
||||||
|
driver.get("http://localhost/");
|
||||||
|
assertThat(driver.getCurrentUrl()).startsWith("https://github.com/login/oauth/authorize");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void defaultLoginPageWithSingleClientRegistrationAndFormLoginThenLinks() {
|
public void defaultLoginPageWithSingleClientRegistrationAndFormLoginThenLinks() {
|
||||||
this.spring.register(OAuth2LoginWithSingleClientRegistrations.class, OAuth2LoginWithFormLogin.class).autowire();
|
this.spring.register(OAuth2LoginWithSingleClientRegistrations.class, OAuth2LoginWithFormLogin.class).autowire();
|
||||||
@ -564,6 +585,16 @@ public class OAuth2LoginTests {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@EnableWebFluxSecurity
|
||||||
|
static class OAuth2LoginWithAuthorizationCodeAndClientCredentialsClientRegistration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
InMemoryReactiveClientRegistrationRepository clientRegistrationRepository() {
|
||||||
|
return new InMemoryReactiveClientRegistrationRepository(github, clientCredentials);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@EnableWebFlux
|
@EnableWebFlux
|
||||||
static class OAuth2AuthorizeWithMockObjectsConfig {
|
static class OAuth2AuthorizeWithMockObjectsConfig {
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user