Register SecurityFilterChain instead of WebSecurityConfigurerAdapter
Closes gh-163
This commit is contained in:
parent
9f246fc304
commit
d97235d0bb
@ -17,21 +17,45 @@ package org.springframework.security.config.annotation.web.configuration;
|
|||||||
|
|
||||||
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.security.config.annotation.web.WebSecurityConfigurer;
|
import org.springframework.core.Ordered;
|
||||||
import org.springframework.security.config.annotation.web.builders.WebSecurity;
|
import org.springframework.core.annotation.Order;
|
||||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.configurers.oauth2.server.authorization.OAuth2AuthorizationServerConfigurer;
|
||||||
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
|
import org.springframework.security.web.util.matcher.OrRequestMatcher;
|
||||||
|
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link Configuration} for OAuth 2.0 Authorization Server support.
|
* {@link Configuration} for OAuth 2.0 Authorization Server support.
|
||||||
*
|
*
|
||||||
* @author Joe Grandja
|
* @author Joe Grandja
|
||||||
* @since 0.0.1
|
* @since 0.0.1
|
||||||
|
* @see OAuth2AuthorizationServerConfigurer
|
||||||
*/
|
*/
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
public class OAuth2AuthorizationServerConfiguration {
|
public class OAuth2AuthorizationServerConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public WebSecurityConfigurer<WebSecurity> defaultOAuth2AuthorizationServerSecurity() {
|
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||||
return new OAuth2AuthorizationServerSecurity();
|
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
|
||||||
|
applyDefaultSecurity(http);
|
||||||
|
return http.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @formatter:off
|
||||||
|
public static void applyDefaultSecurity(HttpSecurity http) throws Exception {
|
||||||
|
OAuth2AuthorizationServerConfigurer<HttpSecurity> authorizationServerConfigurer =
|
||||||
|
new OAuth2AuthorizationServerConfigurer<>();
|
||||||
|
RequestMatcher[] endpointMatchers = authorizationServerConfigurer
|
||||||
|
.getEndpointMatchers().toArray(new RequestMatcher[0]);
|
||||||
|
|
||||||
|
http
|
||||||
|
.requestMatcher(new OrRequestMatcher(endpointMatchers))
|
||||||
|
.authorizeRequests(authorizeRequests ->
|
||||||
|
authorizeRequests.anyRequest().authenticated()
|
||||||
|
)
|
||||||
|
.csrf(csrf -> csrf.ignoringRequestMatchers(endpointMatchers))
|
||||||
|
.apply(authorizationServerConfigurer);
|
||||||
|
}
|
||||||
|
// @formatter:on
|
||||||
}
|
}
|
||||||
|
@ -1,58 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2020 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
|
|
||||||
*
|
|
||||||
* https://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.configuration;
|
|
||||||
|
|
||||||
import org.springframework.core.Ordered;
|
|
||||||
import org.springframework.core.annotation.Order;
|
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
|
||||||
import org.springframework.security.config.annotation.web.configurers.oauth2.server.authorization.OAuth2AuthorizationServerConfigurer;
|
|
||||||
import org.springframework.security.web.util.matcher.OrRequestMatcher;
|
|
||||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
|
||||||
|
|
||||||
import static org.springframework.security.config.Customizer.withDefaults;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link WebSecurityConfigurerAdapter} providing default security configuration for OAuth 2.0 Authorization Server.
|
|
||||||
*
|
|
||||||
* @author Joe Grandja
|
|
||||||
* @since 0.0.1
|
|
||||||
*/
|
|
||||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
|
||||||
public class OAuth2AuthorizationServerSecurity extends WebSecurityConfigurerAdapter {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void configure(HttpSecurity http) throws Exception {
|
|
||||||
applyDefaultConfiguration(http);
|
|
||||||
}
|
|
||||||
|
|
||||||
// @formatter:off
|
|
||||||
public static void applyDefaultConfiguration(HttpSecurity http) throws Exception {
|
|
||||||
OAuth2AuthorizationServerConfigurer<HttpSecurity> authorizationServerConfigurer =
|
|
||||||
new OAuth2AuthorizationServerConfigurer<>();
|
|
||||||
RequestMatcher[] endpointMatchers = authorizationServerConfigurer
|
|
||||||
.getEndpointMatchers().toArray(new RequestMatcher[0]);
|
|
||||||
|
|
||||||
http
|
|
||||||
.requestMatcher(new OrRequestMatcher(endpointMatchers))
|
|
||||||
.authorizeRequests(authorizeRequests ->
|
|
||||||
authorizeRequests.anyRequest().authenticated()
|
|
||||||
)
|
|
||||||
.formLogin(withDefaults())
|
|
||||||
.csrf(csrf -> csrf.ignoringRequestMatchers(endpointMatchers))
|
|
||||||
.apply(authorizationServerConfigurer);
|
|
||||||
}
|
|
||||||
// @formatter:on
|
|
||||||
}
|
|
@ -39,9 +39,13 @@ import org.springframework.security.oauth2.server.authorization.web.OAuth2Author
|
|||||||
import org.springframework.security.oauth2.server.authorization.web.OAuth2ClientAuthenticationFilter;
|
import org.springframework.security.oauth2.server.authorization.web.OAuth2ClientAuthenticationFilter;
|
||||||
import org.springframework.security.oauth2.server.authorization.web.OAuth2TokenEndpointFilter;
|
import org.springframework.security.oauth2.server.authorization.web.OAuth2TokenEndpointFilter;
|
||||||
import org.springframework.security.oauth2.server.authorization.web.OAuth2TokenRevocationEndpointFilter;
|
import org.springframework.security.oauth2.server.authorization.web.OAuth2TokenRevocationEndpointFilter;
|
||||||
|
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||||
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
|
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
|
||||||
|
import org.springframework.security.web.authentication.DelegatingAuthenticationEntryPoint;
|
||||||
import org.springframework.security.web.authentication.HttpStatusEntryPoint;
|
import org.springframework.security.web.authentication.HttpStatusEntryPoint;
|
||||||
|
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
|
||||||
import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter;
|
import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter;
|
||||||
|
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
|
||||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||||
import org.springframework.security.web.util.matcher.OrRequestMatcher;
|
import org.springframework.security.web.util.matcher.OrRequestMatcher;
|
||||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||||
@ -49,6 +53,7 @@ import org.springframework.util.Assert;
|
|||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@ -163,10 +168,19 @@ public final class OAuth2AuthorizationServerConfigurer<B extends HttpSecurityBui
|
|||||||
|
|
||||||
ExceptionHandlingConfigurer<B> exceptionHandling = builder.getConfigurer(ExceptionHandlingConfigurer.class);
|
ExceptionHandlingConfigurer<B> exceptionHandling = builder.getConfigurer(ExceptionHandlingConfigurer.class);
|
||||||
if (exceptionHandling != null) {
|
if (exceptionHandling != null) {
|
||||||
// Register the default AuthenticationEntryPoint for the token endpoint and token revocation endpoint
|
LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> entryPoints = new LinkedHashMap<>();
|
||||||
exceptionHandling.defaultAuthenticationEntryPointFor(
|
entryPoints.put(
|
||||||
new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED),
|
new OrRequestMatcher(this.tokenEndpointMatcher, this.tokenRevocationEndpointMatcher),
|
||||||
new OrRequestMatcher(this.tokenEndpointMatcher, this.tokenRevocationEndpointMatcher));
|
new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED));
|
||||||
|
DelegatingAuthenticationEntryPoint authenticationEntryPoint =
|
||||||
|
new DelegatingAuthenticationEntryPoint(entryPoints);
|
||||||
|
|
||||||
|
// TODO This needs to change as the login page could be customized with a different URL
|
||||||
|
authenticationEntryPoint.setDefaultEntryPoint(
|
||||||
|
new LoginUrlAuthenticationEntryPoint(
|
||||||
|
DefaultLoginPageGeneratingFilter.DEFAULT_LOGIN_PAGE_URL));
|
||||||
|
|
||||||
|
exceptionHandling.authenticationEntryPoint(authenticationEntryPoint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,22 +18,29 @@ package org.springframework.security.config.annotation.web.configuration;
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.springframework.core.Ordered;
|
import org.springframework.core.Ordered;
|
||||||
import org.springframework.core.annotation.OrderUtils;
|
import org.springframework.core.annotation.OrderUtils;
|
||||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
|
import org.springframework.util.ClassUtils;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link OAuth2AuthorizationServerSecurity}.
|
* Tests for {@link OAuth2AuthorizationServerConfiguration}.
|
||||||
*
|
*
|
||||||
* @author Joe Grandja
|
* @author Joe Grandja
|
||||||
*/
|
*/
|
||||||
public class OAuth2AuthorizationServerSecurityTests {
|
public class OAuth2AuthorizationServerConfigurationTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void assertOrderHighestPrecedence() {
|
public void assertOrderHighestPrecedence() {
|
||||||
Integer authorizationServerSecurityOrder = OrderUtils.getOrder(OAuth2AuthorizationServerSecurity.class);
|
Method authorizationServerSecurityFilterChainMethod =
|
||||||
Integer defaultSecurityOrder = OrderUtils.getOrder(WebSecurityConfigurerAdapter.class);
|
ClassUtils.getMethod(
|
||||||
assertThat(authorizationServerSecurityOrder).isNotEqualTo(defaultSecurityOrder);
|
OAuth2AuthorizationServerConfiguration.class,
|
||||||
assertThat(authorizationServerSecurityOrder).isEqualTo(Ordered.HIGHEST_PRECEDENCE);
|
"authorizationServerSecurityFilterChain",
|
||||||
|
HttpSecurity.class);
|
||||||
|
Integer order = OrderUtils.getOrder(authorizationServerSecurityFilterChainMethod);
|
||||||
|
assertThat(order).isEqualTo(Ordered.HIGHEST_PRECEDENCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -16,12 +16,9 @@
|
|||||||
package sample.config;
|
package sample.config;
|
||||||
|
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
|
||||||
import org.springframework.security.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration;
|
import org.springframework.security.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration;
|
||||||
import org.springframework.security.core.userdetails.User;
|
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
|
||||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
|
||||||
import org.springframework.security.crypto.key.CryptoKeySource;
|
import org.springframework.security.crypto.key.CryptoKeySource;
|
||||||
import org.springframework.security.crypto.key.StaticKeyGeneratingCryptoKeySource;
|
import org.springframework.security.crypto.key.StaticKeyGeneratingCryptoKeySource;
|
||||||
import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
||||||
@ -29,7 +26,6 @@ import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
|
|||||||
import org.springframework.security.oauth2.server.authorization.client.InMemoryRegisteredClientRepository;
|
import org.springframework.security.oauth2.server.authorization.client.InMemoryRegisteredClientRepository;
|
||||||
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
|
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
|
||||||
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
|
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
|
||||||
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@ -37,7 +33,7 @@ import java.util.UUID;
|
|||||||
* @author Joe Grandja
|
* @author Joe Grandja
|
||||||
* @since 0.0.1
|
* @since 0.0.1
|
||||||
*/
|
*/
|
||||||
@EnableWebSecurity
|
@Configuration(proxyBeanMethods = false)
|
||||||
@Import(OAuth2AuthorizationServerConfiguration.class)
|
@Import(OAuth2AuthorizationServerConfiguration.class)
|
||||||
public class AuthorizationServerConfig {
|
public class AuthorizationServerConfig {
|
||||||
|
|
||||||
@ -63,16 +59,4 @@ public class AuthorizationServerConfig {
|
|||||||
public CryptoKeySource keySource() {
|
public CryptoKeySource keySource() {
|
||||||
return new StaticKeyGeneratingCryptoKeySource();
|
return new StaticKeyGeneratingCryptoKeySource();
|
||||||
}
|
}
|
||||||
|
|
||||||
// @formatter:off
|
|
||||||
@Bean
|
|
||||||
public UserDetailsService users() {
|
|
||||||
UserDetails user = User.withDefaultPasswordEncoder()
|
|
||||||
.username("user1")
|
|
||||||
.password("password")
|
|
||||||
.roles("USER")
|
|
||||||
.build();
|
|
||||||
return new InMemoryUserDetailsManager(user);
|
|
||||||
}
|
|
||||||
// @formatter:on
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 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
|
||||||
|
*
|
||||||
|
* https://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 sample.config;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
|
import org.springframework.security.core.userdetails.User;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
|
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
||||||
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
|
|
||||||
|
import static org.springframework.security.config.Customizer.withDefaults;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Joe Grandja
|
||||||
|
* @since 0.1.0
|
||||||
|
*/
|
||||||
|
@EnableWebSecurity
|
||||||
|
public class DefaultSecurityConfig {
|
||||||
|
|
||||||
|
// formatter:off
|
||||||
|
@Bean
|
||||||
|
SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
|
||||||
|
http
|
||||||
|
.authorizeRequests(authorizeRequests ->
|
||||||
|
authorizeRequests.anyRequest().authenticated()
|
||||||
|
)
|
||||||
|
.formLogin(withDefaults());
|
||||||
|
return http.build();
|
||||||
|
}
|
||||||
|
// formatter:on
|
||||||
|
|
||||||
|
// @formatter:off
|
||||||
|
@Bean
|
||||||
|
UserDetailsService users() {
|
||||||
|
UserDetails user = User.withDefaultPasswordEncoder()
|
||||||
|
.username("user1")
|
||||||
|
.password("password")
|
||||||
|
.roles("USER")
|
||||||
|
.build();
|
||||||
|
return new InMemoryUserDetailsManager(user);
|
||||||
|
}
|
||||||
|
// @formatter:on
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user