Remove Spring Security OAuth Auto-Configuration

This commit removes auto-configuration support for Spring Security
OAuth, paving the way for the introduction of auto-configuration for
Spring Security 5's new OAuth-related features.

Closes gh-10255
This commit is contained in:
Andy Wilkinson
2017-09-21 10:30:34 +01:00
parent a0fee6fe3b
commit e9147c2f20
79 changed files with 2 additions and 6877 deletions

View File

@@ -1,63 +0,0 @@
/*
* Copyright 2012-2017 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
*
* http://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.boot.autoconfigure.security.oauth2;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.security.oauth2.authserver.OAuth2AuthorizationServerConfiguration;
import org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2RestOperationsConfiguration;
import org.springframework.boot.autoconfigure.security.oauth2.method.OAuth2MethodSecurityConfiguration;
import org.springframework.boot.autoconfigure.security.oauth2.resource.OAuth2ResourceServerConfiguration;
import org.springframework.boot.autoconfigure.security.oauth2.resource.ResourceServerProperties;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* {@link EnableAutoConfiguration Auto-configuration} for Spring Security OAuth2.
*
* @author Greg Turnquist
* @author Dave Syer
* @since 1.3.0
*/
@Configuration
@ConditionalOnClass({ OAuth2AccessToken.class, WebMvcConfigurer.class })
@Import({ OAuth2AuthorizationServerConfiguration.class,
OAuth2MethodSecurityConfiguration.class, OAuth2ResourceServerConfiguration.class,
OAuth2RestOperationsConfiguration.class })
@AutoConfigureBefore(WebMvcAutoConfiguration.class)
@EnableConfigurationProperties(OAuth2ClientProperties.class)
public class OAuth2AutoConfiguration {
private final OAuth2ClientProperties credentials;
public OAuth2AutoConfiguration(OAuth2ClientProperties credentials) {
this.credentials = credentials;
}
@Bean
public ResourceServerProperties resourceServerProperties() {
return new ResourceServerProperties(this.credentials.getClientId(),
this.credentials.getClientSecret());
}
}

View File

@@ -1,66 +0,0 @@
/*
* Copyright 2012-2017 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
*
* http://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.boot.autoconfigure.security.oauth2;
import java.util.UUID;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* Configuration properties for OAuth2 Client.
*
* @author Dave Syer
* @author Stephane Nicoll
* @since 1.3.0
*/
@ConfigurationProperties(prefix = "security.oauth2.client")
public class OAuth2ClientProperties {
/**
* OAuth2 client id.
*/
private String clientId;
/**
* OAuth2 client secret. A random secret is generated by default.
*/
private String clientSecret = UUID.randomUUID().toString();
private boolean defaultSecret = true;
public String getClientId() {
return this.clientId;
}
public void setClientId(String clientId) {
this.clientId = clientId;
}
public String getClientSecret() {
return this.clientSecret;
}
public void setClientSecret(String clientSecret) {
this.clientSecret = clientSecret;
this.defaultSecret = false;
}
public boolean isDefaultSecret() {
return this.defaultSecret;
}
}

View File

@@ -1,74 +0,0 @@
/*
* Copyright 2012-2017 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
*
* http://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.boot.autoconfigure.security.oauth2.authserver;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* Configuration properties for OAuth2 Authorization server.
*
* @author Dave Syer
* @since 1.3.0
*/
@ConfigurationProperties(prefix = "security.oauth2.authorization")
public class AuthorizationServerProperties {
/**
* Spring Security access rule for the check token endpoint (e.g. a SpEL expression
* like "isAuthenticated()") . Default is empty, which is interpreted as "denyAll()"
* (no access).
*/
private String checkTokenAccess;
/**
* Spring Security access rule for the token key endpoint (e.g. a SpEL expression like
* "isAuthenticated()"). Default is empty, which is interpreted as "denyAll()" (no
* access).
*/
private String tokenKeyAccess;
/**
* Realm name for client authentication. If an unauthenticated request comes in to the
* token endpoint, it will respond with a challenge including this name.
*/
private String realm;
public String getCheckTokenAccess() {
return this.checkTokenAccess;
}
public void setCheckTokenAccess(String checkTokenAccess) {
this.checkTokenAccess = checkTokenAccess;
}
public String getTokenKeyAccess() {
return this.tokenKeyAccess;
}
public void setTokenKeyAccess(String tokenKeyAccess) {
this.tokenKeyAccess = tokenKeyAccess;
}
public String getRealm() {
return this.realm;
}
public void setRealm(String realm) {
this.realm = realm;
}
}

View File

@@ -1,204 +0,0 @@
/*
* Copyright 2012-2017 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
*
* http://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.boot.autoconfigure.security.oauth2.authserver;
import java.util.Arrays;
import java.util.Collections;
import java.util.UUID;
import javax.annotation.PostConstruct;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.security.oauth2.OAuth2ClientProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.oauth2.config.annotation.builders.ClientDetailsServiceBuilder;
import org.springframework.security.oauth2.config.annotation.builders.InMemoryClientDetailsServiceBuilder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerEndpointsConfiguration;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.client.BaseClientDetails;
import org.springframework.security.oauth2.provider.token.AccessTokenConverter;
import org.springframework.security.oauth2.provider.token.TokenStore;
/**
* Configuration for a Spring Security OAuth2 authorization server. Back off if another
* {@link AuthorizationServerConfigurer} already exists or if authorization server is not
* enabled.
*
* @author Greg Turnquist
* @author Dave Syer
* @since 1.3.0
*/
@Configuration
@ConditionalOnClass(EnableAuthorizationServer.class)
@ConditionalOnMissingBean(AuthorizationServerConfigurer.class)
@ConditionalOnBean(AuthorizationServerEndpointsConfiguration.class)
@EnableConfigurationProperties(AuthorizationServerProperties.class)
public class OAuth2AuthorizationServerConfiguration
extends AuthorizationServerConfigurerAdapter {
private static final Log logger = LogFactory
.getLog(OAuth2AuthorizationServerConfiguration.class);
private final BaseClientDetails details;
private final AuthenticationManager authenticationManager;
private final TokenStore tokenStore;
private final AccessTokenConverter tokenConverter;
private final AuthorizationServerProperties properties;
public OAuth2AuthorizationServerConfiguration(BaseClientDetails details,
AuthenticationManager authenticationManager,
ObjectProvider<TokenStore> tokenStore,
ObjectProvider<AccessTokenConverter> tokenConverter,
AuthorizationServerProperties properties) {
this.details = details;
this.authenticationManager = authenticationManager;
this.tokenStore = tokenStore.getIfAvailable();
this.tokenConverter = tokenConverter.getIfAvailable();
this.properties = properties;
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
ClientDetailsServiceBuilder<InMemoryClientDetailsServiceBuilder>.ClientBuilder builder = clients
.inMemory().withClient(this.details.getClientId());
builder.secret(this.details.getClientSecret())
.resourceIds(this.details.getResourceIds().toArray(new String[0]))
.authorizedGrantTypes(
this.details.getAuthorizedGrantTypes().toArray(new String[0]))
.authorities(
AuthorityUtils.authorityListToSet(this.details.getAuthorities())
.toArray(new String[0]))
.scopes(this.details.getScope().toArray(new String[0]));
if (this.details.getAutoApproveScopes() != null) {
builder.autoApprove(
this.details.getAutoApproveScopes().toArray(new String[0]));
}
if (this.details.getAccessTokenValiditySeconds() != null) {
builder.accessTokenValiditySeconds(
this.details.getAccessTokenValiditySeconds());
}
if (this.details.getRefreshTokenValiditySeconds() != null) {
builder.refreshTokenValiditySeconds(
this.details.getRefreshTokenValiditySeconds());
}
if (this.details.getRegisteredRedirectUri() != null) {
builder.redirectUris(
this.details.getRegisteredRedirectUri().toArray(new String[0]));
}
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints)
throws Exception {
if (this.tokenConverter != null) {
endpoints.accessTokenConverter(this.tokenConverter);
}
if (this.tokenStore != null) {
endpoints.tokenStore(this.tokenStore);
}
if (this.details.getAuthorizedGrantTypes().contains("password")) {
endpoints.authenticationManager(this.authenticationManager);
}
}
@Override
public void configure(AuthorizationServerSecurityConfigurer security)
throws Exception {
if (this.properties.getCheckTokenAccess() != null) {
security.checkTokenAccess(this.properties.getCheckTokenAccess());
}
if (this.properties.getTokenKeyAccess() != null) {
security.tokenKeyAccess(this.properties.getTokenKeyAccess());
}
if (this.properties.getRealm() != null) {
security.realm(this.properties.getRealm());
}
}
@Configuration
protected static class ClientDetailsLogger {
private final OAuth2ClientProperties credentials;
protected ClientDetailsLogger(OAuth2ClientProperties credentials) {
this.credentials = credentials;
}
@PostConstruct
public void init() {
String prefix = "security.oauth2.client";
boolean defaultSecret = this.credentials.isDefaultSecret();
logger.info(String.format(
"Initialized OAuth2 Client%n%n%s.client-id = %s%n"
+ "%s.client-secret = %s%n%n",
prefix, this.credentials.getClientId(), prefix,
defaultSecret ? this.credentials.getClientSecret() : "****"));
}
}
@Configuration
@ConditionalOnMissingBean(BaseClientDetails.class)
protected static class BaseClientDetailsConfiguration {
private final OAuth2ClientProperties client;
protected BaseClientDetailsConfiguration(OAuth2ClientProperties client) {
this.client = client;
}
@Bean
@ConfigurationProperties(prefix = "security.oauth2.client")
public BaseClientDetails oauth2ClientDetails() {
BaseClientDetails details = new BaseClientDetails();
if (this.client.getClientId() == null) {
this.client.setClientId(UUID.randomUUID().toString());
}
details.setClientId(this.client.getClientId());
details.setClientSecret(this.client.getClientSecret());
details.setAuthorizedGrantTypes(Arrays.asList("authorization_code",
"password", "client_credentials", "implicit", "refresh_token"));
details.setAuthorities(
AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER"));
details.setRegisteredRedirectUri(Collections.<String>emptySet());
return details;
}
}
}

View File

@@ -1,50 +0,0 @@
/*
* Copyright 2012-2017 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
*
* http://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.boot.autoconfigure.security.oauth2.client;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.boot.autoconfigure.security.oauth2.resource.ResourceServerTokenServicesConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Import;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client;
/**
* Enable OAuth2 Single Sign On (SSO). If there is an existing
* {@link WebSecurityConfigurerAdapter} provided by the user and annotated with
* {@code @EnableOAuth2Sso}, it is enhanced by adding an authentication filter and an
* authentication entry point. If the user only has {@code @EnableOAuth2Sso} but not on a
* WebSecurityConfigurerAdapter then one is added with all paths secured.
*
* @author Dave Syer
* @since 1.3.0
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@EnableOAuth2Client
@EnableConfigurationProperties(OAuth2SsoProperties.class)
@Import({ OAuth2SsoDefaultConfiguration.class, OAuth2SsoCustomConfiguration.class,
ResourceServerTokenServicesConfiguration.class })
public @interface EnableOAuth2Sso {
}

View File

@@ -1,54 +0,0 @@
/*
* Copyright 2012-2016 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
*
* http://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.boot.autoconfigure.security.oauth2.client;
import org.springframework.boot.autoconfigure.condition.ConditionMessage;
import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
/**
* Condition that checks for {@link EnableOAuth2Sso} on a
* {@link WebSecurityConfigurerAdapter}.
*
* @author Dave Syer
*/
class EnableOAuth2SsoCondition extends SpringBootCondition {
@Override
public ConditionOutcome getMatchOutcome(ConditionContext context,
AnnotatedTypeMetadata metadata) {
String[] enablers = context.getBeanFactory()
.getBeanNamesForAnnotation(EnableOAuth2Sso.class);
ConditionMessage.Builder message = ConditionMessage
.forCondition("@EnableOAuth2Sso Condition");
for (String name : enablers) {
if (context.getBeanFactory().isTypeMatch(name,
WebSecurityConfigurerAdapter.class)) {
return ConditionOutcome.match(message
.found("@EnableOAuth2Sso annotation on WebSecurityConfigurerAdapter")
.items(name));
}
}
return ConditionOutcome.noMatch(message.didNotFind(
"@EnableOAuth2Sso annotation " + "on any WebSecurityConfigurerAdapter")
.atAll());
}
}

View File

@@ -1,40 +0,0 @@
/*
* Copyright 2012-2017 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
*
* http://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.boot.autoconfigure.security.oauth2.client;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails;
/**
* Shared {@link AuthorizationCodeResourceDetails} configuration.
*
* @author Stephane Nicoll
*/
@Configuration
class OAuth2ProtectedResourceDetailsConfiguration {
@Bean
@ConfigurationProperties(prefix = "security.oauth2.client")
@Primary
public AuthorizationCodeResourceDetails oauth2RemoteResource() {
return new AuthorizationCodeResourceDetails();
}
}

View File

@@ -1,209 +0,0 @@
/*
* Copyright 2012-2017 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
*
* http://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.boot.autoconfigure.security.oauth2.client;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.AnyNestedCondition;
import org.springframework.boot.autoconfigure.condition.ConditionMessage;
import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnNotWebApplication;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.NoneNestedConditions;
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.client.DefaultOAuth2ClientContext;
import org.springframework.security.oauth2.client.filter.OAuth2ClientContextFilter;
import org.springframework.security.oauth2.client.token.AccessTokenRequest;
import org.springframework.security.oauth2.client.token.DefaultAccessTokenRequest;
import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsResourceDetails;
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client;
import org.springframework.security.oauth2.config.annotation.web.configuration.OAuth2ClientConfiguration;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails;
import org.springframework.util.StringUtils;
/**
* Configuration for OAuth2 Single Sign On REST operations.
*
* @author Dave Syer
* @author Madhura Bhave
* @since 1.3.0
*/
@Configuration
@ConditionalOnClass(EnableOAuth2Client.class)
public class OAuth2RestOperationsConfiguration {
@Configuration
@Conditional(ClientCredentialsCondition.class)
protected static class SingletonScopedConfiguration {
@Bean
@ConfigurationProperties(prefix = "security.oauth2.client")
@Primary
public ClientCredentialsResourceDetails oauth2RemoteResource() {
ClientCredentialsResourceDetails details = new ClientCredentialsResourceDetails();
return details;
}
@Bean
public DefaultOAuth2ClientContext oauth2ClientContext() {
return new DefaultOAuth2ClientContext(new DefaultAccessTokenRequest());
}
}
@Configuration
@ConditionalOnBean(OAuth2ClientConfiguration.class)
@Conditional({ OAuth2ClientIdCondition.class, NoClientCredentialsCondition.class })
@Import(OAuth2ProtectedResourceDetailsConfiguration.class)
protected static class SessionScopedConfiguration {
@Bean
public FilterRegistrationBean<OAuth2ClientContextFilter> oauth2ClientFilterRegistration(
OAuth2ClientContextFilter filter, SecurityProperties security) {
FilterRegistrationBean<OAuth2ClientContextFilter> registration = new FilterRegistrationBean<>();
registration.setFilter(filter);
registration.setOrder(security.getFilter().getOrder() - 10);
return registration;
}
@Configuration
protected static class ClientContextConfiguration {
private final AccessTokenRequest accessTokenRequest;
public ClientContextConfiguration(
@Qualifier("accessTokenRequest") ObjectProvider<AccessTokenRequest> accessTokenRequest) {
this.accessTokenRequest = accessTokenRequest.getIfAvailable();
}
@Bean
@Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES)
public DefaultOAuth2ClientContext oauth2ClientContext() {
return new DefaultOAuth2ClientContext(this.accessTokenRequest);
}
}
}
// When the authentication is per cookie but the stored token is an oauth2 one, we can
// pass that on to a client that wants to call downstream. We don't even need an
// OAuth2ClientContextFilter until we need to refresh the access token. To handle
// refresh tokens you need to @EnableOAuth2Client
@Configuration
@ConditionalOnMissingBean(OAuth2ClientConfiguration.class)
@Conditional({ OAuth2ClientIdCondition.class, NoClientCredentialsCondition.class })
@Import(OAuth2ProtectedResourceDetailsConfiguration.class)
protected static class RequestScopedConfiguration {
@Bean
@Scope(value = "request", proxyMode = ScopedProxyMode.INTERFACES)
public DefaultOAuth2ClientContext oauth2ClientContext() {
DefaultOAuth2ClientContext context = new DefaultOAuth2ClientContext(
new DefaultAccessTokenRequest());
Authentication principal = SecurityContextHolder.getContext()
.getAuthentication();
if (principal instanceof OAuth2Authentication) {
OAuth2Authentication authentication = (OAuth2Authentication) principal;
Object details = authentication.getDetails();
if (details instanceof OAuth2AuthenticationDetails) {
OAuth2AuthenticationDetails oauthsDetails = (OAuth2AuthenticationDetails) details;
String token = oauthsDetails.getTokenValue();
context.setAccessToken(new DefaultOAuth2AccessToken(token));
}
}
return context;
}
}
/**
* Condition to check if a {@code security.oauth2.client.client-id} is specified.
*/
static class OAuth2ClientIdCondition extends SpringBootCondition {
@Override
public ConditionOutcome getMatchOutcome(ConditionContext context,
AnnotatedTypeMetadata metadata) {
String clientId = context.getEnvironment()
.getProperty("security.oauth2.client.client-id");
ConditionMessage.Builder message = ConditionMessage
.forCondition("OAuth Client ID");
if (StringUtils.hasLength(clientId)) {
return ConditionOutcome.match(message
.foundExactly("security.oauth2.client.client-id property"));
}
return ConditionOutcome.noMatch(message
.didNotFind("security.oauth2.client.client-id property").atAll());
}
}
/**
* Condition to check for no client credentials.
*/
static class NoClientCredentialsCondition extends NoneNestedConditions {
NoClientCredentialsCondition() {
super(ConfigurationPhase.PARSE_CONFIGURATION);
}
@Conditional(ClientCredentialsCondition.class)
static class ClientCredentialsActivated {
}
}
/**
* Condition to check for client credentials.
*/
static class ClientCredentialsCondition extends AnyNestedCondition {
ClientCredentialsCondition() {
super(ConfigurationPhase.PARSE_CONFIGURATION);
}
@ConditionalOnProperty(prefix = "security.oauth2.client", name = "grant-type", havingValue = "client_credentials", matchIfMissing = false)
static class ClientCredentialsConfigured {
}
@ConditionalOnNotWebApplication
static class NoWebApplication {
}
}
}

View File

@@ -1,109 +0,0 @@
/*
* Copyright 2012-2016 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
*
* http://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.boot.autoconfigure.security.oauth2.client;
import java.lang.reflect.Method;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportAware;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
/**
* Configuration for OAuth2 Single Sign On (SSO) when there is an existing
* {@link WebSecurityConfigurerAdapter} provided by the user and annotated with
* {@code @EnableOAuth2Sso}. The user-provided configuration is enhanced by adding an
* authentication filter and an authentication entry point.
*
* @author Dave Syer
*/
@Configuration
@Conditional(EnableOAuth2SsoCondition.class)
public class OAuth2SsoCustomConfiguration
implements ImportAware, BeanPostProcessor, ApplicationContextAware {
private Class<?> configType;
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@Override
public void setImportMetadata(AnnotationMetadata importMetadata) {
this.configType = ClassUtils.resolveClassName(importMetadata.getClassName(),
null);
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
if (this.configType.isAssignableFrom(bean.getClass())
&& bean instanceof WebSecurityConfigurerAdapter) {
ProxyFactory factory = new ProxyFactory();
factory.setTarget(bean);
factory.addAdvice(new SsoSecurityAdapter(this.applicationContext));
bean = factory.getProxy();
}
return bean;
}
private static class SsoSecurityAdapter implements MethodInterceptor {
private SsoSecurityConfigurer configurer;
SsoSecurityAdapter(ApplicationContext applicationContext) {
this.configurer = new SsoSecurityConfigurer(applicationContext);
}
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
if (invocation.getMethod().getName().equals("init")) {
Method method = ReflectionUtils
.findMethod(WebSecurityConfigurerAdapter.class, "getHttp");
ReflectionUtils.makeAccessible(method);
HttpSecurity http = (HttpSecurity) ReflectionUtils.invokeMethod(method,
invocation.getThis());
this.configurer.configure(http);
}
return invocation.proceed();
}
}
}

View File

@@ -1,63 +0,0 @@
/*
* Copyright 2012-2017 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
*
* http://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.boot.autoconfigure.security.oauth2.client;
import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
import org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2SsoDefaultConfiguration.NeedsWebSecurityCondition;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
/**
* Configuration for OAuth2 Single Sign On (SSO). If the user only has
* {@code @EnableOAuth2Sso} but not on a {@code WebSecurityConfigurerAdapter} then one is
* added with all paths secured.
*
* @author Dave Syer
* @since 1.3.0
*/
@Configuration
@Conditional(NeedsWebSecurityCondition.class)
public class OAuth2SsoDefaultConfiguration extends WebSecurityConfigurerAdapter {
private final ApplicationContext applicationContext;
public OAuth2SsoDefaultConfiguration(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/**").authorizeRequests().anyRequest().authenticated();
new SsoSecurityConfigurer(this.applicationContext).configure(http);
}
protected static class NeedsWebSecurityCondition extends EnableOAuth2SsoCondition {
@Override
public ConditionOutcome getMatchOutcome(ConditionContext context,
AnnotatedTypeMetadata metadata) {
return ConditionOutcome.inverse(super.getMatchOutcome(context, metadata));
}
}
}

View File

@@ -1,46 +0,0 @@
/*
* Copyright 2012-2017 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
*
* http://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.boot.autoconfigure.security.oauth2.client;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* Configuration properties for OAuth2 Single Sign On (SSO).
*
* @author Dave Syer
* @since 1.3.0
*/
@ConfigurationProperties(prefix = "security.oauth2.sso")
public class OAuth2SsoProperties {
public static final String DEFAULT_LOGIN_PATH = "/login";
/**
* Path to the login page, i.e. the one that triggers the redirect to the OAuth2
* Authorization Server.
*/
private String loginPath = DEFAULT_LOGIN_PATH;
public String getLoginPath() {
return this.loginPath;
}
public void setLoginPath(String loginPath) {
this.loginPath = loginPath;
}
}

View File

@@ -1,119 +0,0 @@
/*
* Copyright 2012-2016 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
*
* http://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.boot.autoconfigure.security.oauth2.client;
import java.util.Collections;
import org.springframework.boot.autoconfigure.security.oauth2.resource.UserInfoRestTemplateFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.ExceptionHandlingConfigurer;
import org.springframework.security.oauth2.client.OAuth2RestOperations;
import org.springframework.security.oauth2.client.filter.OAuth2ClientAuthenticationProcessingFilter;
import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;
import org.springframework.security.web.DefaultSecurityFilterChain;
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.session.SessionAuthenticationStrategy;
import org.springframework.security.web.util.matcher.MediaTypeRequestMatcher;
import org.springframework.security.web.util.matcher.RequestHeaderRequestMatcher;
import org.springframework.web.accept.ContentNegotiationStrategy;
import org.springframework.web.accept.HeaderContentNegotiationStrategy;
/**
* Configurer for OAuth2 Single Sign On (SSO).
*
* @author Dave Syer
*/
class SsoSecurityConfigurer {
private ApplicationContext applicationContext;
SsoSecurityConfigurer(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
public void configure(HttpSecurity http) throws Exception {
OAuth2SsoProperties sso = this.applicationContext
.getBean(OAuth2SsoProperties.class);
// Delay the processing of the filter until we know the
// SessionAuthenticationStrategy is available:
http.apply(new OAuth2ClientAuthenticationConfigurer(oauth2SsoFilter(sso)));
addAuthenticationEntryPoint(http, sso);
}
private void addAuthenticationEntryPoint(HttpSecurity http, OAuth2SsoProperties sso)
throws Exception {
ExceptionHandlingConfigurer<HttpSecurity> exceptions = http.exceptionHandling();
ContentNegotiationStrategy contentNegotiationStrategy = http
.getSharedObject(ContentNegotiationStrategy.class);
if (contentNegotiationStrategy == null) {
contentNegotiationStrategy = new HeaderContentNegotiationStrategy();
}
MediaTypeRequestMatcher preferredMatcher = new MediaTypeRequestMatcher(
contentNegotiationStrategy, MediaType.APPLICATION_XHTML_XML,
new MediaType("image", "*"), MediaType.TEXT_HTML, MediaType.TEXT_PLAIN);
preferredMatcher.setIgnoredMediaTypes(Collections.singleton(MediaType.ALL));
exceptions.defaultAuthenticationEntryPointFor(
new LoginUrlAuthenticationEntryPoint(sso.getLoginPath()),
preferredMatcher);
// When multiple entry points are provided the default is the first one
exceptions.defaultAuthenticationEntryPointFor(
new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED),
new RequestHeaderRequestMatcher("X-Requested-With", "XMLHttpRequest"));
}
private OAuth2ClientAuthenticationProcessingFilter oauth2SsoFilter(
OAuth2SsoProperties sso) {
OAuth2RestOperations restTemplate = this.applicationContext
.getBean(UserInfoRestTemplateFactory.class).getUserInfoRestTemplate();
ResourceServerTokenServices tokenServices = this.applicationContext
.getBean(ResourceServerTokenServices.class);
OAuth2ClientAuthenticationProcessingFilter filter = new OAuth2ClientAuthenticationProcessingFilter(
sso.getLoginPath());
filter.setRestTemplate(restTemplate);
filter.setTokenServices(tokenServices);
filter.setApplicationEventPublisher(this.applicationContext);
return filter;
}
private static class OAuth2ClientAuthenticationConfigurer
extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {
private OAuth2ClientAuthenticationProcessingFilter filter;
OAuth2ClientAuthenticationConfigurer(
OAuth2ClientAuthenticationProcessingFilter filter) {
this.filter = filter;
}
@Override
public void configure(HttpSecurity builder) throws Exception {
OAuth2ClientAuthenticationProcessingFilter ssoFilter = this.filter;
ssoFilter.setSessionAuthenticationStrategy(
builder.getSharedObject(SessionAuthenticationStrategy.class));
builder.addFilterAfter(ssoFilter,
AbstractPreAuthenticatedProcessingFilter.class);
}
}
}

View File

@@ -1,115 +0,0 @@
/*
* Copyright 2012-2017 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
*
* http://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.boot.autoconfigure.security.oauth2.method;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
import org.springframework.security.authentication.AuthenticationTrustResolver;
import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.expression.OAuth2MethodSecurityExpressionHandler;
/**
* Auto-configure an expression handler for method-level security (if the user already has
* {@code @EnableGlobalMethodSecurity}).
*
* @author Greg Turnquist
* @author Dave Syer
* @since 1.3.0
*/
@Configuration
@ConditionalOnClass({ OAuth2AccessToken.class })
@ConditionalOnBean(GlobalMethodSecurityConfiguration.class)
public class OAuth2MethodSecurityConfiguration
implements BeanFactoryPostProcessor, ApplicationContextAware {
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.applicationContext = applicationContext;
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
throws BeansException {
OAuth2ExpressionHandlerInjectionPostProcessor processor = new OAuth2ExpressionHandlerInjectionPostProcessor(
this.applicationContext);
beanFactory.addBeanPostProcessor(processor);
}
private static class OAuth2ExpressionHandlerInjectionPostProcessor
implements BeanPostProcessor {
private ApplicationContext applicationContext;
OAuth2ExpressionHandlerInjectionPostProcessor(
ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
if (bean instanceof DefaultMethodSecurityExpressionHandler
&& !(bean instanceof OAuth2MethodSecurityExpressionHandler)) {
return getExpressionHandler(
(DefaultMethodSecurityExpressionHandler) bean);
}
return bean;
}
private OAuth2MethodSecurityExpressionHandler getExpressionHandler(
DefaultMethodSecurityExpressionHandler bean) {
OAuth2MethodSecurityExpressionHandler handler = new OAuth2MethodSecurityExpressionHandler();
handler.setApplicationContext(this.applicationContext);
AuthenticationTrustResolver trustResolver = findInContext(
AuthenticationTrustResolver.class);
if (trustResolver != null) {
handler.setTrustResolver(trustResolver);
}
handler.setExpressionParser(bean.getExpressionParser());
return handler;
}
private <T> T findInContext(Class<T> type) {
if (BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.applicationContext, type).length == 1) {
return this.applicationContext.getBean(type);
}
return null;
}
}
}

View File

@@ -1,41 +0,0 @@
/*
* Copyright 2012-2017 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
*
* http://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.boot.autoconfigure.security.oauth2.resource;
import java.util.List;
import java.util.Map;
import org.springframework.security.core.GrantedAuthority;
/**
* Strategy used by {@link UserInfoTokenServices} to extract authorities from the resource
* server's response.
*
* @author Dave Syer
* @since 1.3.0
*/
@FunctionalInterface
public interface AuthoritiesExtractor {
/**
* Extract the authorities from the resource server's response.
* @param map the response
* @return the extracted authorities
*/
List<GrantedAuthority> extractAuthorities(Map<String, Object> map);
}

View File

@@ -1,97 +0,0 @@
/*
* Copyright 2012-2017 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
*
* http://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.boot.autoconfigure.security.oauth2.resource;
import java.util.List;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.security.oauth2.resource.ResourceServerTokenServicesConfiguration.AcceptJsonRequestEnhancer;
import org.springframework.boot.autoconfigure.security.oauth2.resource.ResourceServerTokenServicesConfiguration.AcceptJsonRequestInterceptor;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.security.oauth2.client.OAuth2ClientContext;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeAccessTokenProvider;
import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails;
import org.springframework.util.CollectionUtils;
/**
* Factory used to create the {@link OAuth2RestTemplate} used for extracting user info
* during authentication if none is available.
*
* @author Dave Syer
* @author Stephane Nicoll
* @since 1.5.0
*/
public class DefaultUserInfoRestTemplateFactory implements UserInfoRestTemplateFactory {
private static final AuthorizationCodeResourceDetails DEFAULT_RESOURCE_DETAILS;
static {
AuthorizationCodeResourceDetails details = new AuthorizationCodeResourceDetails();
details.setClientId("<N/A>");
details.setUserAuthorizationUri("Not a URI because there is no client");
details.setAccessTokenUri("Not a URI because there is no client");
DEFAULT_RESOURCE_DETAILS = details;
}
private final List<UserInfoRestTemplateCustomizer> customizers;
private final OAuth2ProtectedResourceDetails details;
private final OAuth2ClientContext oauth2ClientContext;
private OAuth2RestTemplate oauth2RestTemplate;
public DefaultUserInfoRestTemplateFactory(
ObjectProvider<List<UserInfoRestTemplateCustomizer>> customizers,
ObjectProvider<OAuth2ProtectedResourceDetails> details,
ObjectProvider<OAuth2ClientContext> oauth2ClientContext) {
this.customizers = customizers.getIfAvailable();
this.details = details.getIfAvailable();
this.oauth2ClientContext = oauth2ClientContext.getIfAvailable();
}
@Override
public OAuth2RestTemplate getUserInfoRestTemplate() {
if (this.oauth2RestTemplate == null) {
this.oauth2RestTemplate = createOAuth2RestTemplate(
this.details == null ? DEFAULT_RESOURCE_DETAILS : this.details);
this.oauth2RestTemplate.getInterceptors()
.add(new AcceptJsonRequestInterceptor());
AuthorizationCodeAccessTokenProvider accessTokenProvider = new AuthorizationCodeAccessTokenProvider();
accessTokenProvider.setTokenRequestEnhancer(new AcceptJsonRequestEnhancer());
this.oauth2RestTemplate.setAccessTokenProvider(accessTokenProvider);
if (!CollectionUtils.isEmpty(this.customizers)) {
AnnotationAwareOrderComparator.sort(this.customizers);
for (UserInfoRestTemplateCustomizer customizer : this.customizers) {
customizer.customize(this.oauth2RestTemplate);
}
}
}
return this.oauth2RestTemplate;
}
private OAuth2RestTemplate createOAuth2RestTemplate(
OAuth2ProtectedResourceDetails details) {
if (this.oauth2ClientContext == null) {
return new OAuth2RestTemplate(details);
}
return new OAuth2RestTemplate(details, this.oauth2ClientContext);
}
}

View File

@@ -1,88 +0,0 @@
/*
* Copyright 2012-2017 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
*
* http://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.boot.autoconfigure.security.oauth2.resource;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
/**
* Default implementation of {@link AuthoritiesExtractor}. Extracts the authorities from
* the map with the key {@code authorities}. If no such value exists, a single
* {@code ROLE_USER} authority is returned.
*
* @author Dave Syer
* @since 1.3.0
*/
public class FixedAuthoritiesExtractor implements AuthoritiesExtractor {
private static final String AUTHORITIES = "authorities";
private static final String[] AUTHORITY_KEYS = { "authority", "role", "value" };
@Override
public List<GrantedAuthority> extractAuthorities(Map<String, Object> map) {
String authorities = "ROLE_USER";
if (map.containsKey(AUTHORITIES)) {
authorities = asAuthorities(map.get(AUTHORITIES));
}
return AuthorityUtils.commaSeparatedStringToAuthorityList(authorities);
}
private String asAuthorities(Object object) {
List<Object> authorities = new ArrayList<>();
if (object instanceof Collection) {
Collection<?> collection = (Collection<?>) object;
object = collection.toArray(new Object[0]);
}
if (ObjectUtils.isArray(object)) {
Object[] array = (Object[]) object;
for (Object value : array) {
if (value instanceof String) {
authorities.add(value);
}
else if (value instanceof Map) {
authorities.add(asAuthority((Map<?, ?>) value));
}
else {
authorities.add(value);
}
}
return StringUtils.collectionToCommaDelimitedString(authorities);
}
return object.toString();
}
private Object asAuthority(Map<?, ?> map) {
if (map.size() == 1) {
return map.values().iterator().next();
}
for (String key : AUTHORITY_KEYS) {
if (map.containsKey(key)) {
return map.get(key);
}
}
return map;
}
}

View File

@@ -1,43 +0,0 @@
/*
* Copyright 2012-2016 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
*
* http://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.boot.autoconfigure.security.oauth2.resource;
import java.util.Map;
/**
* Default implementation of {@link PrincipalExtractor}. Extracts the principal from the
* map with well known keys.
*
* @author Phillip Webb
* @since 1.4.0
*/
public class FixedPrincipalExtractor implements PrincipalExtractor {
private static final String[] PRINCIPAL_KEYS = new String[] { "user", "username",
"userid", "user_id", "login", "id", "name" };
@Override
public Object extractPrincipal(Map<String, Object> map) {
for (String key : PRINCIPAL_KEYS) {
if (map.containsKey(key)) {
return map.get(key);
}
}
return null;
}
}

View File

@@ -1,37 +0,0 @@
/*
* Copyright 2012-2017 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
*
* http://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.boot.autoconfigure.security.oauth2.resource;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
/**
* Callback interface that can be used to provide additional configuration to the
* {@link JwtAccessTokenConverter}.
*
* @author Dave Syer
* @since 1.3.0
*/
@FunctionalInterface
public interface JwtAccessTokenConverterConfigurer {
/**
* Configure the {@link JwtAccessTokenConverter}.
* @param converter the converter to configure
*/
void configure(JwtAccessTokenConverter converter);
}

View File

@@ -1,40 +0,0 @@
/*
* Copyright 2012-2017 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
*
* http://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.boot.autoconfigure.security.oauth2.resource;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.web.client.RestTemplate;
/**
* Callback for customizing the {@link RestTemplate} that is used to fetch the keys used
* by {@link JwtAccessTokenConverter}.
*
* @author Eddú Meléndez
* @since 1.5.2
* @see JwtAccessTokenConverter#setSigningKey(String)
* @see JwtAccessTokenConverter#setVerifierKey(String)
*/
@FunctionalInterface
public interface JwtAccessTokenConverterRestTemplateCustomizer {
/**
* Customize the {@code template} before it is initialized.
* @param template the rest template
*/
void customize(RestTemplate template);
}

View File

@@ -1,190 +0,0 @@
/*
* Copyright 2012-2017 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
*
* http://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.boot.autoconfigure.security.oauth2.resource;
import java.util.Map;
import org.springframework.beans.BeanUtils;
import org.springframework.boot.autoconfigure.condition.ConditionMessage;
import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.boot.autoconfigure.security.oauth2.resource.OAuth2ResourceServerConfiguration.ResourceServerCondition;
import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ConfigurationCondition;
import org.springframework.context.annotation.Import;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.core.type.StandardAnnotationMetadata;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerEndpointsConfiguration;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfiguration;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
/**
* Auto-configure a Spring Security OAuth2 resource server. Back off if another
* {@link ResourceServerConfigurer} already exists or if resource server not enabled.
*
* @author Greg Turnquist
* @author Dave Syer
* @author Madhura Bhave
* @since 1.3.0
*/
@Configuration
@Conditional(ResourceServerCondition.class)
@ConditionalOnClass({ EnableResourceServer.class, SecurityProperties.class })
@ConditionalOnWebApplication
@ConditionalOnBean(ResourceServerConfiguration.class)
@Import(ResourceServerTokenServicesConfiguration.class)
public class OAuth2ResourceServerConfiguration {
private final ResourceServerProperties resource;
public OAuth2ResourceServerConfiguration(ResourceServerProperties resource) {
this.resource = resource;
}
@Bean
@ConditionalOnMissingBean(ResourceServerConfigurer.class)
public ResourceServerConfigurer resourceServer() {
return new ResourceSecurityConfigurer(this.resource);
}
protected static class ResourceSecurityConfigurer
extends ResourceServerConfigurerAdapter {
private ResourceServerProperties resource;
public ResourceSecurityConfigurer(ResourceServerProperties resource) {
this.resource = resource;
}
@Override
public void configure(ResourceServerSecurityConfigurer resources)
throws Exception {
resources.resourceId(this.resource.getResourceId());
}
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated();
}
}
protected static class ResourceServerCondition extends SpringBootCondition
implements ConfigurationCondition {
private static final Bindable<Map<String, Object>> STRING_OBJECT_MAP = Bindable
.mapOf(String.class, Object.class);
private static final String AUTHORIZATION_ANNOTATION = "org.springframework."
+ "security.oauth2.config.annotation.web.configuration."
+ "AuthorizationServerEndpointsConfiguration";
@Override
public ConfigurationPhase getConfigurationPhase() {
return ConfigurationPhase.REGISTER_BEAN;
}
@Override
public ConditionOutcome getMatchOutcome(ConditionContext context,
AnnotatedTypeMetadata metadata) {
ConditionMessage.Builder message = ConditionMessage
.forCondition("OAuth ResourceServer Condition");
Environment environment = context.getEnvironment();
if (!(environment instanceof ConfigurableEnvironment)) {
return ConditionOutcome
.noMatch(message.didNotFind("A ConfigurableEnvironment").atAll());
}
if (hasOAuthClientId(environment)) {
return ConditionOutcome.match(message.foundExactly("client-id property"));
}
Binder binder = Binder.get(environment);
String prefix = "security.oauth2.resource.";
if (binder.bind(prefix + "jwt", STRING_OBJECT_MAP).isBound()) {
return ConditionOutcome
.match(message.foundExactly("JWT resource configuration"));
}
if (binder.bind(prefix + "jwk", STRING_OBJECT_MAP).isBound()) {
return ConditionOutcome
.match(message.foundExactly("JWK resource configuration"));
}
if (StringUtils.hasText(environment.getProperty(prefix + "user-info-uri"))) {
return ConditionOutcome
.match(message.foundExactly("user-info-uri property"));
}
if (StringUtils.hasText(environment.getProperty(prefix + "token-info-uri"))) {
return ConditionOutcome
.match(message.foundExactly("token-info-uri property"));
}
if (ClassUtils.isPresent(AUTHORIZATION_ANNOTATION, null)) {
if (AuthorizationServerEndpointsConfigurationBeanCondition
.matches(context)) {
return ConditionOutcome.match(
message.found("class").items(AUTHORIZATION_ANNOTATION));
}
}
return ConditionOutcome.noMatch(
message.didNotFind("client ID, JWT resource or authorization server")
.atAll());
}
private boolean hasOAuthClientId(Environment environment) {
return StringUtils.hasLength(
environment.getProperty("security.oauth2.client.client-id"));
}
}
@ConditionalOnBean(AuthorizationServerEndpointsConfiguration.class)
private static class AuthorizationServerEndpointsConfigurationBeanCondition {
public static boolean matches(ConditionContext context) {
Class<AuthorizationServerEndpointsConfigurationBeanCondition> type = AuthorizationServerEndpointsConfigurationBeanCondition.class;
Conditional conditional = AnnotationUtils.findAnnotation(type,
Conditional.class);
StandardAnnotationMetadata metadata = new StandardAnnotationMetadata(type);
for (Class<? extends Condition> conditionType : conditional.value()) {
Condition condition = BeanUtils.instantiateClass(conditionType);
if (condition.matches(context, metadata)) {
return true;
}
}
return false;
}
}
}

View File

@@ -1,38 +0,0 @@
/*
* Copyright 2012-2017 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
*
* http://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.boot.autoconfigure.security.oauth2.resource;
import java.util.Map;
/**
* Strategy used by {@link UserInfoTokenServices} to extract the principal from the
* resource server's response.
*
* @author Phillip Webb
* @since 1.4.0
*/
@FunctionalInterface
public interface PrincipalExtractor {
/**
* Extract the principal that should be used for the token.
* @param map the source map
* @return the extracted principal or {@code null}
*/
Object extractPrincipal(Map<String, Object> map);
}

View File

@@ -1,284 +0,0 @@
/*
* Copyright 2012-2017 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
*
* http://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.boot.autoconfigure.security.oauth2.resource;
import javax.annotation.PostConstruct;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerEndpointsConfiguration;
import org.springframework.util.StringUtils;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
/**
* Configuration properties for OAuth2 Resources.
*
* @author Dave Syer
* @author Madhura Bhave
* @since 1.3.0
*/
@ConfigurationProperties(prefix = "security.oauth2.resource")
public class ResourceServerProperties implements BeanFactoryAware {
@JsonIgnore
private final String clientId;
@JsonIgnore
private final String clientSecret;
@JsonIgnore
private ListableBeanFactory beanFactory;
private String serviceId = "resource";
/**
* Identifier of the resource.
*/
private String id;
/**
* URI of the user endpoint.
*/
private String userInfoUri;
/**
* URI of the token decoding endpoint.
*/
private String tokenInfoUri;
/**
* Use the token info, can be set to false to use the user info.
*/
private boolean preferTokenInfo = true;
/**
* The token type to send when using the userInfoUri.
*/
private String tokenType = DefaultOAuth2AccessToken.BEARER_TYPE;
private Jwt jwt = new Jwt();
private Jwk jwk = new Jwk();
public ResourceServerProperties() {
this(null, null);
}
public ResourceServerProperties(String clientId, String clientSecret) {
this.clientId = clientId;
this.clientSecret = clientSecret;
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = (ListableBeanFactory) beanFactory;
}
public String getResourceId() {
return this.id;
}
public String getServiceId() {
return this.serviceId;
}
public void setServiceId(String serviceId) {
this.serviceId = serviceId;
}
public String getId() {
return this.id;
}
public void setId(String id) {
this.id = id;
}
public String getUserInfoUri() {
return this.userInfoUri;
}
public void setUserInfoUri(String userInfoUri) {
this.userInfoUri = userInfoUri;
}
public String getTokenInfoUri() {
return this.tokenInfoUri;
}
public void setTokenInfoUri(String tokenInfoUri) {
this.tokenInfoUri = tokenInfoUri;
}
public boolean isPreferTokenInfo() {
return this.preferTokenInfo;
}
public void setPreferTokenInfo(boolean preferTokenInfo) {
this.preferTokenInfo = preferTokenInfo;
}
public String getTokenType() {
return this.tokenType;
}
public void setTokenType(String tokenType) {
this.tokenType = tokenType;
}
public Jwt getJwt() {
return this.jwt;
}
public void setJwt(Jwt jwt) {
this.jwt = jwt;
}
public Jwk getJwk() {
return this.jwk;
}
public void setJwk(Jwk jwk) {
this.jwk = jwk;
}
public String getClientId() {
return this.clientId;
}
public String getClientSecret() {
return this.clientSecret;
}
@PostConstruct
public void validate() {
if (countBeans(AuthorizationServerEndpointsConfiguration.class) > 0) {
// If we are an authorization server we don't need remote resource token
// services
return;
}
if (countBeans(ResourceServerTokenServicesConfiguration.class) == 0) {
// If we are not a resource server or an SSO client we don't need remote
// resource token services
return;
}
if (!StringUtils.hasText(this.clientId)) {
return;
}
try {
doValidate();
}
catch (BindException ex) {
throw new IllegalStateException(ex);
}
}
private int countBeans(Class<?> type) {
return BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, type,
true, false).length;
}
private void doValidate() throws BindException {
BindingResult errors = new BeanPropertyBindingResult(this,
"resourceServerProperties");
boolean jwtConfigPresent = StringUtils.hasText(this.jwt.getKeyUri())
|| StringUtils.hasText(this.jwt.getKeyValue());
boolean jwkConfigPresent = StringUtils.hasText(this.jwk.getKeySetUri());
if (jwtConfigPresent && jwkConfigPresent) {
errors.reject("ambiguous.keyUri",
"Only one of jwt.keyUri (or jwt.keyValue) and jwk.keySetUri should"
+ " be configured.");
}
if (!jwtConfigPresent && !jwkConfigPresent) {
if (!StringUtils.hasText(this.userInfoUri)
&& !StringUtils.hasText(this.tokenInfoUri)) {
errors.rejectValue("tokenInfoUri", "missing.tokenInfoUri",
"Missing tokenInfoUri and userInfoUri and there is no "
+ "JWT verifier key");
}
if (StringUtils.hasText(this.tokenInfoUri) && isPreferTokenInfo()) {
if (!StringUtils.hasText(this.clientSecret)) {
errors.rejectValue("clientSecret", "missing.clientSecret",
"Missing client secret");
}
}
}
if (errors.hasErrors()) {
throw new BindException(errors);
}
}
public class Jwt {
/**
* The verification key of the JWT token. Can either be a symmetric secret or
* PEM-encoded RSA public key. If the value is not available, you can set the URI
* instead.
*/
private String keyValue;
/**
* The URI of the JWT token. Can be set if the value is not available and the key
* is public.
*/
private String keyUri;
public String getKeyValue() {
return this.keyValue;
}
public void setKeyValue(String keyValue) {
this.keyValue = keyValue;
}
public void setKeyUri(String keyUri) {
this.keyUri = keyUri;
}
public String getKeyUri() {
return this.keyUri;
}
}
public class Jwk {
/**
* The URI to get verification keys to verify the JWT token. This can be set when
* the authorization server returns a set of verification keys.
*/
private String keySetUri;
public String getKeySetUri() {
return this.keySetUri;
}
public void setKeySetUri(String keySetUri) {
this.keySetUri = keySetUri;
}
}
}

View File

@@ -1,443 +0,0 @@
/*
* Copyright 2012-2017 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
*
* http://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.boot.autoconfigure.security.oauth2.resource;
import java.io.IOException;
import java.util.Arrays;
import java.util.Base64;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.condition.ConditionMessage;
import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
import org.springframework.boot.autoconfigure.condition.NoneNestedConditions;
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpRequest;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.security.oauth2.client.OAuth2ClientContext;
import org.springframework.security.oauth2.client.OAuth2RestOperations;
import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
import org.springframework.security.oauth2.client.token.AccessTokenRequest;
import org.springframework.security.oauth2.client.token.RequestEnhancer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerEndpointsConfiguration;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.RemoteTokenServices;
import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.security.oauth2.provider.token.store.jwk.JwkTokenStore;
import org.springframework.social.connect.ConnectionFactoryLocator;
import org.springframework.social.connect.support.OAuth2ConnectionFactory;
import org.springframework.util.CollectionUtils;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
/**
* Configuration for an OAuth2 resource server.
*
* @author Dave Syer
* @author Madhura Bhave
* @author Eddú Meléndez
* @since 1.3.0
*/
@Configuration
@ConditionalOnMissingBean(AuthorizationServerEndpointsConfiguration.class)
public class ResourceServerTokenServicesConfiguration {
@Bean
@ConditionalOnMissingBean
public UserInfoRestTemplateFactory userInfoRestTemplateFactory(
ObjectProvider<List<UserInfoRestTemplateCustomizer>> customizers,
ObjectProvider<OAuth2ProtectedResourceDetails> details,
ObjectProvider<OAuth2ClientContext> oauth2ClientContext) {
return new DefaultUserInfoRestTemplateFactory(customizers, details,
oauth2ClientContext);
}
@Configuration
@Conditional(RemoteTokenCondition.class)
protected static class RemoteTokenServicesConfiguration {
@Configuration
@Conditional(TokenInfoCondition.class)
protected static class TokenInfoServicesConfiguration {
private final ResourceServerProperties resource;
protected TokenInfoServicesConfiguration(ResourceServerProperties resource) {
this.resource = resource;
}
@Bean
public RemoteTokenServices remoteTokenServices() {
RemoteTokenServices services = new RemoteTokenServices();
services.setCheckTokenEndpointUrl(this.resource.getTokenInfoUri());
services.setClientId(this.resource.getClientId());
services.setClientSecret(this.resource.getClientSecret());
return services;
}
}
@Configuration
@ConditionalOnClass(OAuth2ConnectionFactory.class)
@Conditional(NotTokenInfoCondition.class)
protected static class SocialTokenServicesConfiguration {
private final ResourceServerProperties sso;
private final OAuth2ConnectionFactory<?> connectionFactory;
private final OAuth2RestOperations restTemplate;
private final AuthoritiesExtractor authoritiesExtractor;
private final PrincipalExtractor principalExtractor;
public SocialTokenServicesConfiguration(ResourceServerProperties sso,
ObjectProvider<OAuth2ConnectionFactory<?>> connectionFactory,
UserInfoRestTemplateFactory restTemplateFactory,
ObjectProvider<AuthoritiesExtractor> authoritiesExtractor,
ObjectProvider<PrincipalExtractor> principalExtractor) {
this.sso = sso;
this.connectionFactory = connectionFactory.getIfAvailable();
this.restTemplate = restTemplateFactory.getUserInfoRestTemplate();
this.authoritiesExtractor = authoritiesExtractor.getIfAvailable();
this.principalExtractor = principalExtractor.getIfAvailable();
}
@Bean
@ConditionalOnBean(ConnectionFactoryLocator.class)
@ConditionalOnMissingBean(ResourceServerTokenServices.class)
public SpringSocialTokenServices socialTokenServices() {
return new SpringSocialTokenServices(this.connectionFactory,
this.sso.getClientId());
}
@Bean
@ConditionalOnMissingBean({ ConnectionFactoryLocator.class,
ResourceServerTokenServices.class })
public UserInfoTokenServices userInfoTokenServices() {
UserInfoTokenServices services = new UserInfoTokenServices(
this.sso.getUserInfoUri(), this.sso.getClientId());
services.setTokenType(this.sso.getTokenType());
services.setRestTemplate(this.restTemplate);
if (this.authoritiesExtractor != null) {
services.setAuthoritiesExtractor(this.authoritiesExtractor);
}
if (this.principalExtractor != null) {
services.setPrincipalExtractor(this.principalExtractor);
}
return services;
}
}
@Configuration
@ConditionalOnMissingClass("org.springframework.social.connect.support.OAuth2ConnectionFactory")
@Conditional(NotTokenInfoCondition.class)
protected static class UserInfoTokenServicesConfiguration {
private final ResourceServerProperties sso;
private final OAuth2RestOperations restTemplate;
private final AuthoritiesExtractor authoritiesExtractor;
private final PrincipalExtractor principalExtractor;
public UserInfoTokenServicesConfiguration(ResourceServerProperties sso,
UserInfoRestTemplateFactory restTemplateFactory,
ObjectProvider<AuthoritiesExtractor> authoritiesExtractor,
ObjectProvider<PrincipalExtractor> principalExtractor) {
this.sso = sso;
this.restTemplate = restTemplateFactory.getUserInfoRestTemplate();
this.authoritiesExtractor = authoritiesExtractor.getIfAvailable();
this.principalExtractor = principalExtractor.getIfAvailable();
}
@Bean
@ConditionalOnMissingBean(ResourceServerTokenServices.class)
public UserInfoTokenServices userInfoTokenServices() {
UserInfoTokenServices services = new UserInfoTokenServices(
this.sso.getUserInfoUri(), this.sso.getClientId());
services.setRestTemplate(this.restTemplate);
services.setTokenType(this.sso.getTokenType());
if (this.authoritiesExtractor != null) {
services.setAuthoritiesExtractor(this.authoritiesExtractor);
}
if (this.principalExtractor != null) {
services.setPrincipalExtractor(this.principalExtractor);
}
return services;
}
}
}
@Configuration
@Conditional(JwkCondition.class)
protected static class JwkTokenStoreConfiguration {
private final ResourceServerProperties resource;
public JwkTokenStoreConfiguration(ResourceServerProperties resource) {
this.resource = resource;
}
@Bean
@ConditionalOnMissingBean(ResourceServerTokenServices.class)
public DefaultTokenServices jwkTokenServices(TokenStore jwkTokenStore) {
DefaultTokenServices services = new DefaultTokenServices();
services.setTokenStore(jwkTokenStore);
return services;
}
@Bean
@ConditionalOnMissingBean(TokenStore.class)
public TokenStore jwkTokenStore() {
return new JwkTokenStore(this.resource.getJwk().getKeySetUri());
}
}
@Configuration
@Conditional(JwtTokenCondition.class)
protected static class JwtTokenServicesConfiguration {
private final ResourceServerProperties resource;
private final List<JwtAccessTokenConverterConfigurer> configurers;
private final List<JwtAccessTokenConverterRestTemplateCustomizer> customizers;
public JwtTokenServicesConfiguration(ResourceServerProperties resource,
ObjectProvider<List<JwtAccessTokenConverterConfigurer>> configurers,
ObjectProvider<List<JwtAccessTokenConverterRestTemplateCustomizer>> customizers) {
this.resource = resource;
this.configurers = configurers.getIfAvailable();
this.customizers = customizers.getIfAvailable();
}
@Bean
@ConditionalOnMissingBean(ResourceServerTokenServices.class)
public DefaultTokenServices jwtTokenServices(TokenStore jwtTokenStore) {
DefaultTokenServices services = new DefaultTokenServices();
services.setTokenStore(jwtTokenStore);
return services;
}
@Bean
@ConditionalOnMissingBean(TokenStore.class)
public TokenStore jwtTokenStore() {
return new JwtTokenStore(jwtTokenEnhancer());
}
@Bean
public JwtAccessTokenConverter jwtTokenEnhancer() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
String keyValue = this.resource.getJwt().getKeyValue();
if (!StringUtils.hasText(keyValue)) {
keyValue = getKeyFromServer();
}
if (StringUtils.hasText(keyValue) && !keyValue.startsWith("-----BEGIN")) {
converter.setSigningKey(keyValue);
}
if (keyValue != null) {
converter.setVerifierKey(keyValue);
}
if (!CollectionUtils.isEmpty(this.configurers)) {
AnnotationAwareOrderComparator.sort(this.configurers);
for (JwtAccessTokenConverterConfigurer configurer : this.configurers) {
configurer.configure(converter);
}
}
return converter;
}
private String getKeyFromServer() {
RestTemplate keyUriRestTemplate = new RestTemplate();
if (!CollectionUtils.isEmpty(this.customizers)) {
for (JwtAccessTokenConverterRestTemplateCustomizer customizer : this.customizers) {
customizer.customize(keyUriRestTemplate);
}
}
HttpHeaders headers = new HttpHeaders();
String username = this.resource.getClientId();
String password = this.resource.getClientSecret();
if (username != null && password != null) {
byte[] token = Base64.getEncoder()
.encode((username + ":" + password).getBytes());
headers.add("Authorization", "Basic " + new String(token));
}
HttpEntity<Void> request = new HttpEntity<>(headers);
String url = this.resource.getJwt().getKeyUri();
return (String) keyUriRestTemplate
.exchange(url, HttpMethod.GET, request, Map.class).getBody()
.get("value");
}
}
private static class TokenInfoCondition extends SpringBootCondition {
@Override
public ConditionOutcome getMatchOutcome(ConditionContext context,
AnnotatedTypeMetadata metadata) {
ConditionMessage.Builder message = ConditionMessage
.forCondition("OAuth TokenInfo Condition");
Environment environment = context.getEnvironment();
Boolean preferTokenInfo = environment.getProperty(
"security.oauth2.resource.prefer-token-info", Boolean.class);
if (preferTokenInfo == null) {
preferTokenInfo = environment
.resolvePlaceholders("${OAUTH2_RESOURCE_PREFERTOKENINFO:true}")
.equals("true");
}
String tokenInfoUri = environment
.getProperty("security.oauth2.resource.token-info-uri");
String userInfoUri = environment
.getProperty("security.oauth2.resource.user-info-uri");
if (!StringUtils.hasLength(userInfoUri)
&& !StringUtils.hasLength(tokenInfoUri)) {
return ConditionOutcome
.match(message.didNotFind("user-info-uri property").atAll());
}
if (StringUtils.hasLength(tokenInfoUri) && preferTokenInfo) {
return ConditionOutcome
.match(message.foundExactly("preferred token-info-uri property"));
}
return ConditionOutcome.noMatch(message.didNotFind("token info").atAll());
}
}
private static class JwtTokenCondition extends SpringBootCondition {
@Override
public ConditionOutcome getMatchOutcome(ConditionContext context,
AnnotatedTypeMetadata metadata) {
ConditionMessage.Builder message = ConditionMessage
.forCondition("OAuth JWT Condition");
Environment environment = context.getEnvironment();
String keyValue = environment
.getProperty("security.oauth2.resource.jwt.key-value");
String keyUri = environment
.getProperty("security.oauth2.resource.jwt.key-uri");
if (StringUtils.hasText(keyValue) || StringUtils.hasText(keyUri)) {
return ConditionOutcome
.match(message.foundExactly("provided public key"));
}
return ConditionOutcome
.noMatch(message.didNotFind("provided public key").atAll());
}
}
private static class JwkCondition extends SpringBootCondition {
@Override
public ConditionOutcome getMatchOutcome(ConditionContext context,
AnnotatedTypeMetadata metadata) {
ConditionMessage.Builder message = ConditionMessage
.forCondition("OAuth JWK Condition");
Environment environment = context.getEnvironment();
String keyUri = environment
.getProperty("security.oauth2.resource.jwk.key-set-uri");
if (StringUtils.hasText(keyUri)) {
return ConditionOutcome
.match(message.foundExactly("provided jwk key set URI"));
}
return ConditionOutcome
.noMatch(message.didNotFind("key jwk set URI not provided").atAll());
}
}
private static class NotTokenInfoCondition extends SpringBootCondition {
private TokenInfoCondition tokenInfoCondition = new TokenInfoCondition();
@Override
public ConditionOutcome getMatchOutcome(ConditionContext context,
AnnotatedTypeMetadata metadata) {
return ConditionOutcome
.inverse(this.tokenInfoCondition.getMatchOutcome(context, metadata));
}
}
private static class RemoteTokenCondition extends NoneNestedConditions {
RemoteTokenCondition() {
super(ConfigurationPhase.PARSE_CONFIGURATION);
}
@Conditional(JwtTokenCondition.class)
static class HasJwtConfiguration {
}
@Conditional(JwkCondition.class)
static class HasJwkConfiguration {
}
}
static class AcceptJsonRequestInterceptor implements ClientHttpRequestInterceptor {
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body,
ClientHttpRequestExecution execution) throws IOException {
request.getHeaders().setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
return execution.execute(request, body);
}
}
static class AcceptJsonRequestEnhancer implements RequestEnhancer {
@Override
public void enhance(AccessTokenRequest request,
OAuth2ProtectedResourceDetails resource,
MultiValueMap<String, String> form, HttpHeaders headers) {
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
}
}
}

View File

@@ -1,77 +0,0 @@
/*
* Copyright 2012-2016 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
*
* http://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.boot.autoconfigure.security.oauth2.resource;
import java.util.List;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.OAuth2Request;
import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;
import org.springframework.social.connect.Connection;
import org.springframework.social.connect.UserProfile;
import org.springframework.social.connect.support.OAuth2ConnectionFactory;
import org.springframework.social.oauth2.AccessGrant;
/**
* {@link ResourceServerTokenServices} backed by Spring Social.
*
* @author Dave Syer
* @since 1.3.0
*/
public class SpringSocialTokenServices implements ResourceServerTokenServices {
private final OAuth2ConnectionFactory<?> connectionFactory;
private final String clientId;
public SpringSocialTokenServices(OAuth2ConnectionFactory<?> connectionFactory,
String clientId) {
this.connectionFactory = connectionFactory;
this.clientId = clientId;
}
@Override
public OAuth2Authentication loadAuthentication(String accessToken)
throws AuthenticationException, InvalidTokenException {
AccessGrant accessGrant = new AccessGrant(accessToken);
Connection<?> connection = this.connectionFactory.createConnection(accessGrant);
UserProfile user = connection.fetchUserProfile();
return extractAuthentication(user);
}
private OAuth2Authentication extractAuthentication(UserProfile user) {
String principal = user.getUsername();
List<GrantedAuthority> authorities = AuthorityUtils
.commaSeparatedStringToAuthorityList("ROLE_USER");
OAuth2Request request = new OAuth2Request(null, this.clientId, null, true, null,
null, null, null, null);
return new OAuth2Authentication(request,
new UsernamePasswordAuthenticationToken(principal, "N/A", authorities));
}
@Override
public OAuth2AccessToken readAccessToken(String accessToken) {
throw new UnsupportedOperationException("Not supported: read access token");
}
}

View File

@@ -1,41 +0,0 @@
/*
* Copyright 2012-2017 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
*
* http://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.boot.autoconfigure.security.oauth2.resource;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
/**
* Callback for customizing the rest template used to fetch user details if authentication
* is done via OAuth2 access tokens. The default should be fine for most providers, but
* occasionally you might need to add additional interceptors, or change the request
* authenticator (which is how the token gets attached to outgoing requests). The rest
* template that is being customized here is <i>only</i> used internally to carry out
* authentication (in the SSO or Resource Server use cases).
*
* @author Dave Syer
* @since 1.3.0
*/
@FunctionalInterface
public interface UserInfoRestTemplateCustomizer {
/**
* Customize the rest template before it is initialized.
* @param template the rest template
*/
void customize(OAuth2RestTemplate template);
}

View File

@@ -1,39 +0,0 @@
/*
* Copyright 2012-2017 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
*
* http://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.boot.autoconfigure.security.oauth2.resource;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
/**
* Factory used to create the {@link OAuth2RestTemplate} used for extracting user info
* during authentication if none is available.
*
* @author Dave Syer
* @author Stephane Nicoll
* @since 1.4.0
*/
@FunctionalInterface
public interface UserInfoRestTemplateFactory {
/**
* Return the {@link OAuth2RestTemplate} used for extracting user info during
* authentication if none is available.
* @return the OAuth2RestTemplate used for authentication
*/
OAuth2RestTemplate getUserInfoRestTemplate();
}

View File

@@ -1,156 +0,0 @@
/*
* Copyright 2012-2017 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
*
* http://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.boot.autoconfigure.security.oauth2.resource;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.oauth2.client.OAuth2RestOperations;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
import org.springframework.security.oauth2.client.resource.BaseOAuth2ProtectedResourceDetails;
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.OAuth2Request;
import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;
import org.springframework.util.Assert;
/**
* {@link ResourceServerTokenServices} that uses a user info REST service.
*
* @author Dave Syer
* @since 1.3.0
*/
public class UserInfoTokenServices implements ResourceServerTokenServices {
protected final Log logger = LogFactory.getLog(getClass());
private final String userInfoEndpointUrl;
private final String clientId;
private OAuth2RestOperations restTemplate;
private String tokenType = DefaultOAuth2AccessToken.BEARER_TYPE;
private AuthoritiesExtractor authoritiesExtractor = new FixedAuthoritiesExtractor();
private PrincipalExtractor principalExtractor = new FixedPrincipalExtractor();
public UserInfoTokenServices(String userInfoEndpointUrl, String clientId) {
this.userInfoEndpointUrl = userInfoEndpointUrl;
this.clientId = clientId;
}
public void setTokenType(String tokenType) {
this.tokenType = tokenType;
}
public void setRestTemplate(OAuth2RestOperations restTemplate) {
this.restTemplate = restTemplate;
}
public void setAuthoritiesExtractor(AuthoritiesExtractor authoritiesExtractor) {
Assert.notNull(authoritiesExtractor, "AuthoritiesExtractor must not be null");
this.authoritiesExtractor = authoritiesExtractor;
}
public void setPrincipalExtractor(PrincipalExtractor principalExtractor) {
Assert.notNull(principalExtractor, "PrincipalExtractor must not be null");
this.principalExtractor = principalExtractor;
}
@Override
public OAuth2Authentication loadAuthentication(String accessToken)
throws AuthenticationException, InvalidTokenException {
Map<String, Object> map = getMap(this.userInfoEndpointUrl, accessToken);
if (map.containsKey("error")) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("userinfo returned error: " + map.get("error"));
}
throw new InvalidTokenException(accessToken);
}
return extractAuthentication(map);
}
private OAuth2Authentication extractAuthentication(Map<String, Object> map) {
Object principal = getPrincipal(map);
List<GrantedAuthority> authorities = this.authoritiesExtractor
.extractAuthorities(map);
OAuth2Request request = new OAuth2Request(null, this.clientId, null, true, null,
null, null, null, null);
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
principal, "N/A", authorities);
token.setDetails(map);
return new OAuth2Authentication(request, token);
}
/**
* Return the principal that should be used for the token. The default implementation
* delegates to the {@link PrincipalExtractor}.
* @param map the source map
* @return the principal or {@literal "unknown"}
*/
protected Object getPrincipal(Map<String, Object> map) {
Object principal = this.principalExtractor.extractPrincipal(map);
return (principal == null ? "unknown" : principal);
}
@Override
public OAuth2AccessToken readAccessToken(String accessToken) {
throw new UnsupportedOperationException("Not supported: read access token");
}
@SuppressWarnings({ "unchecked" })
private Map<String, Object> getMap(String path, String accessToken) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Getting user info from: " + path);
}
try {
OAuth2RestOperations restTemplate = this.restTemplate;
if (restTemplate == null) {
BaseOAuth2ProtectedResourceDetails resource = new BaseOAuth2ProtectedResourceDetails();
resource.setClientId(this.clientId);
restTemplate = new OAuth2RestTemplate(resource);
}
OAuth2AccessToken existingToken = restTemplate.getOAuth2ClientContext()
.getAccessToken();
if (existingToken == null || !accessToken.equals(existingToken.getValue())) {
DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken(
accessToken);
token.setTokenType(this.tokenType);
restTemplate.getOAuth2ClientContext().setAccessToken(token);
}
return restTemplate.getForEntity(path, Map.class).getBody();
}
catch (Exception ex) {
this.logger.warn("Could not fetch user details: " + ex.getClass() + ", "
+ ex.getMessage());
return Collections.<String, Object>singletonMap("error",
"Could not fetch user details");
}
}
}

View File

@@ -895,25 +895,6 @@
"level": "error"
}
},
{
"name": "security.oauth2.resource.filter-order",
"type": "java.lang.Integer",
"description": "The order of the filter chain used to authenticate tokens. Default puts it after\n the actuator endpoints and before the default HTTP basic filter chain (catchall).",
"defaultValue": 0,
"deprecation": {
"reason": "The security auto-configuration does no longer provide several security configurations. Their ordering is now explicit in your own security configuration.",
"level": "error"
}
},
{
"name": "security.oauth2.sso.filter-order",
"type": "java.lang.Integer",
"description": "Filter order to apply if not providing an explicit WebSecurityConfigurerAdapter (in\n which case the order can be provided there instead).",
"deprecation": {
"reason": "The security auto-configuration does no longer provide several security configurations. Their ordering is now explicit in your own security configuration.",
"level": "error"
}
},
{
"name": "security.require-ssl",
"type": "java.lang.Boolean",

View File

@@ -98,7 +98,6 @@ org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration,\
org.springframework.boot.autoconfigure.reactor.core.ReactorCoreAutoConfiguration,\
org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.SecurityFilterAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.OAuth2AutoConfiguration,\
org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\
org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\
org.springframework.boot.autoconfigure.social.SocialWebAutoConfiguration,\