diff --git a/pom.xml b/pom.xml
index 79fe022..16fdbde 100644
--- a/pom.xml
+++ b/pom.xml
@@ -65,6 +65,7 @@
org.springframework.social
spring-social-core
+ true
org.projectlombok
diff --git a/src/main/java/org/springframework/cloud/cloudfoundry/oauth2/ClientConfiguration.java b/src/main/java/org/springframework/cloud/cloudfoundry/oauth2/ClientConfiguration.java
new file mode 100644
index 0000000..c3f6e45
--- /dev/null
+++ b/src/main/java/org/springframework/cloud/cloudfoundry/oauth2/ClientConfiguration.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2013-2014 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.cloud.cloudfoundry.oauth2;
+
+import java.io.IOException;
+import java.util.Arrays;
+
+import javax.annotation.Resource;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.context.embedded.FilterRegistrationBean;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Scope;
+import org.springframework.context.annotation.ScopedProxyMode;
+import org.springframework.http.HttpHeaders;
+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.DefaultOAuth2ClientContext;
+import org.springframework.security.oauth2.client.OAuth2ClientContext;
+import org.springframework.security.oauth2.client.OAuth2RestOperations;
+import org.springframework.security.oauth2.client.OAuth2RestTemplate;
+import org.springframework.security.oauth2.client.filter.OAuth2ClientContextFilter;
+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.client.token.grant.code.AuthorizationCodeAccessTokenProvider;
+import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails;
+import org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client;
+import org.springframework.util.MultiValueMap;
+
+/**
+ * @author Dave Syer
+ *
+ */
+@Configuration
+@EnableOAuth2Client
+@EnableConfigurationProperties(OAuth2ClientProperties.class)
+public class ClientConfiguration {
+
+ @Autowired
+ private OAuth2ClientProperties sso;
+
+ @Resource
+ @Qualifier("accessTokenRequest")
+ private AccessTokenRequest accessTokenRequest;
+
+ @Bean
+ public FilterRegistrationBean oauth2ClientFilterRegistration(
+ OAuth2ClientContextFilter filter) {
+ FilterRegistrationBean registration = new FilterRegistrationBean();
+ registration.setFilter(filter);
+ registration.setOrder(0);
+ return registration;
+ }
+
+ @Bean
+ public OAuth2ProtectedResourceDetails oauth2RemoteResource() {
+ AuthorizationCodeResourceDetails details = new AuthorizationCodeResourceDetails();
+ // set up resource details, OAuth2 URLs etc.
+ details.setClientId(sso.getClientId());
+ details.setClientSecret(sso.getClientSecret());
+ details.setAccessTokenUri(sso.getTokenUri());
+ details.setUserAuthorizationUri(sso.getAuthorizationUri());
+ details.setClientAuthenticationScheme(sso.getAuthenticationScheme());
+ return details;
+ }
+
+ @Bean
+ public OAuth2RestOperations oauth2RestTemplate() {
+ OAuth2RestTemplate template = new OAuth2RestTemplate(oauth2RemoteResource(),
+ oauth2ClientContext());
+ template.setInterceptors(Arrays
+ . asList(new 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);
+ }
+ }));
+ AuthorizationCodeAccessTokenProvider accessTokenProvider = new AuthorizationCodeAccessTokenProvider();
+ accessTokenProvider.setTokenRequestEnhancer(new RequestEnhancer() {
+ @Override
+ public void enhance(AccessTokenRequest request,
+ OAuth2ProtectedResourceDetails resource,
+ MultiValueMap form, HttpHeaders headers) {
+ headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
+ }
+ });
+ template.setAccessTokenProvider(accessTokenProvider);
+ return template;
+ }
+
+ @Bean
+ @Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES)
+ public OAuth2ClientContext oauth2ClientContext() {
+ return new DefaultOAuth2ClientContext(accessTokenRequest);
+ }
+
+}
diff --git a/src/main/java/org/springframework/cloud/cloudfoundry/oauth2/OAuth2ClientProperties.java b/src/main/java/org/springframework/cloud/cloudfoundry/oauth2/OAuth2ClientProperties.java
new file mode 100644
index 0000000..5bf5651
--- /dev/null
+++ b/src/main/java/org/springframework/cloud/cloudfoundry/oauth2/OAuth2ClientProperties.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2013-2014 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.cloud.cloudfoundry.oauth2;
+
+import lombok.Data;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.security.oauth2.common.AuthenticationScheme;
+import org.springframework.util.StringUtils;
+import org.springframework.validation.Errors;
+import org.springframework.validation.Validator;
+
+/**
+ * @author Dave Syer
+ *
+ */
+@ConfigurationProperties("oauth2.client")
+@Data
+public class OAuth2ClientProperties implements Validator {
+
+ @Value("${vcap.services.${oauth2.sso.serviceId:sso}.credentials.tokenUri:${vcap.services.${oauth2.resource.serviceId:resource}.credentials.tokenUri:}}")
+ private String tokenUri;
+
+ @Value("${vcap.services.${oauth2.sso.serviceId:sso}.credentials.authorizationUri:${vcap.services.${oauth2.resource.serviceId:resource}.credentials.authorizationUri:}}")
+ private String authorizationUri;
+
+ @Value("${vcap.services.${oauth2.sso.serviceId:sso}.credentials.clientId:${vcap.services.${oauth2.resource.serviceId:resource}.credentials.clientId:}}")
+ private String clientId;
+
+ @Value("${vcap.services.${oauth2.sso.serviceId:sso}.credentials.clientSecret:${vcap.services.${oauth2.resource.serviceId:resource}.credentials.clientSecret:}}")
+ private String clientSecret;
+
+ private AuthenticationScheme authenticationScheme = AuthenticationScheme.header;
+
+ @Override
+ public boolean supports(Class> clazz) {
+ return OAuth2ClientProperties.class.isAssignableFrom(clazz);
+ }
+
+ @Override
+ public void validate(Object target, Errors errors) {
+ OAuth2ClientProperties sso = (OAuth2ClientProperties) target;
+ if (StringUtils.hasText(sso.getClientId())) {
+ if (!StringUtils.hasText(sso.getAuthorizationUri())) {
+ errors.rejectValue("authorizeUri", "missing.authorizeUri",
+ "Missing authorizeUri");
+ }
+ if (!StringUtils.hasText(sso.getTokenUri())) {
+ errors.rejectValue("tokenUri", "missing.tokenUri", "Missing tokenUri");
+ }
+ if (!StringUtils.hasText(sso.getClientSecret())) {
+ errors.rejectValue("clientSecret", "missing.clientSecret",
+ "Missing clientSecret");
+ }
+ }
+ }
+
+}
diff --git a/src/main/java/org/springframework/cloud/cloudfoundry/oauth2/ResourceServerProperties.java b/src/main/java/org/springframework/cloud/cloudfoundry/oauth2/ResourceServerProperties.java
index 0832fd3..6649b59 100644
--- a/src/main/java/org/springframework/cloud/cloudfoundry/oauth2/ResourceServerProperties.java
+++ b/src/main/java/org/springframework/cloud/cloudfoundry/oauth2/ResourceServerProperties.java
@@ -16,7 +16,9 @@
package org.springframework.cloud.cloudfoundry.oauth2;
import lombok.Data;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.util.StringUtils;
@@ -29,19 +31,16 @@ import org.springframework.validation.Validator;
*/
@ConfigurationProperties("oauth2.resource")
@Data
+@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class ResourceServerProperties implements Validator {
+
+ private final OAuth2ClientProperties client;
private String serviceId = "resource";
@Value("${vcap.services.${oauth2.resource.serviceId:resource}.credentials.id:}")
private String id;
- @Value("${vcap.services.${oauth2.resource.serviceId:resource}.credentials.clientId:${vcap.services.${oauth2.sso.serviceId:sso}.credentials.clientId:}}")
- private String clientId;
-
- @Value("${vcap.services.${oauth2.resource.serviceId:resource}.credentials.clientSecret:${vcap.services.${oauth2.sso.serviceId:sso}.credentials.clientSecret:}}")
- private String clientSecret;
-
@Value("${vcap.services.${oauth2.resource.serviceId:resource}.credentials.userInfoUri:${vcap.services.${oauth2.sso.serviceId:sso}.credentials.userInfoUri:}}")
private String userInfoUri;
@@ -51,7 +50,7 @@ public class ResourceServerProperties implements Validator {
private boolean preferTokenInfo = true;
public String getResourceId() {
- return !StringUtils.hasText(id) ? clientId : id;
+ return id;
}
@Override
@@ -62,8 +61,8 @@ public class ResourceServerProperties implements Validator {
@Override
public void validate(Object target, Errors errors) {
ResourceServerProperties resource = (ResourceServerProperties) target;
- if (StringUtils.hasText(resource.getClientId())) {
- if (!StringUtils.hasText(resource.getClientSecret())) {
+ if (StringUtils.hasText(client.getClientId())) {
+ if (!StringUtils.hasText(client.getClientSecret())) {
if (!StringUtils.hasText(resource.getUserInfoUri())) {
errors.rejectValue("userInfoUri", "missing.userInfoUri",
"Missing userInfoUri (no client secret available)");
diff --git a/src/main/java/org/springframework/cloud/cloudfoundry/oauth2/ResourceServerTokenServicesConfiguration.java b/src/main/java/org/springframework/cloud/cloudfoundry/oauth2/ResourceServerTokenServicesConfiguration.java
index 42a8e11..fce767e 100644
--- a/src/main/java/org/springframework/cloud/cloudfoundry/oauth2/ResourceServerTokenServicesConfiguration.java
+++ b/src/main/java/org/springframework/cloud/cloudfoundry/oauth2/ResourceServerTokenServicesConfiguration.java
@@ -16,7 +16,6 @@
package org.springframework.cloud.cloudfoundry.oauth2;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
@@ -25,7 +24,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClas
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
-import org.springframework.security.oauth2.client.OAuth2RestOperations;
+import org.springframework.context.annotation.Import;
import org.springframework.security.oauth2.provider.token.RemoteTokenServices;
import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;
import org.springframework.social.connect.support.OAuth2ConnectionFactory;
@@ -36,19 +35,23 @@ import org.springframework.social.connect.support.OAuth2ConnectionFactory;
*/
@Configuration
@EnableConfigurationProperties(ResourceServerProperties.class)
+@Import(ClientConfiguration.class)
public class ResourceServerTokenServicesConfiguration {
@Autowired
private ResourceServerProperties resource;
+ @Autowired
+ private OAuth2ClientProperties client;
+
@Bean
@ConditionalOnMissingBean(ResourceServerTokenServices.class)
@ConditionalOnExpression("${oauth2.resource.preferTokenInfo:${OAUTH2_RESOURCE_PREFERTOKENINFO:true}}")
protected RemoteTokenServices remoteTokenServices() {
RemoteTokenServices services = new RemoteTokenServices();
services.setCheckTokenEndpointUrl(resource.getTokenInfoUri());
- services.setClientId(resource.getClientId());
- services.setClientSecret(resource.getClientSecret());
+ services.setClientId(client.getClientId());
+ services.setClientSecret(client.getClientSecret());
return services;
}
@@ -60,26 +63,24 @@ public class ResourceServerTokenServicesConfiguration {
@Autowired
private ResourceServerProperties sso;
- @Autowired(required = false)
- private OAuth2ConnectionFactory> connectionFactory;
+ @Autowired
+ private OAuth2ClientProperties client;
@Autowired(required = false)
- @Qualifier("oauth2RestTemplate")
- private OAuth2RestOperations restTemplate;
+ private OAuth2ConnectionFactory> connectionFactory;
@Bean
@ConditionalOnBean(OAuth2ConnectionFactory.class)
@ConditionalOnMissingBean(ResourceServerTokenServices.class)
public SpringSocialTokenServices socialTokenServices() {
- return new SpringSocialTokenServices(connectionFactory, sso.getClientId());
+ return new SpringSocialTokenServices(connectionFactory, client.getClientId());
}
@Bean
@ConditionalOnMissingBean({ OAuth2ConnectionFactory.class,
ResourceServerTokenServices.class })
public UserInfoTokenServices userInfoTokenServices() {
- return new UserInfoTokenServices(restTemplate, sso.getUserInfoUri(),
- sso.getClientId());
+ return new UserInfoTokenServices(sso.getUserInfoUri(), client.getClientId());
}
}
@@ -93,14 +94,12 @@ public class ResourceServerTokenServicesConfiguration {
private ResourceServerProperties sso;
@Autowired
- @Qualifier("oauth2RestTemplate")
- private OAuth2RestOperations restTemplate;
+ private OAuth2ClientProperties client;
@Bean
@ConditionalOnMissingBean(ResourceServerTokenServices.class)
public UserInfoTokenServices userInfoTokenServices() {
- return new UserInfoTokenServices(restTemplate, sso.getUserInfoUri(),
- sso.getClientId());
+ return new UserInfoTokenServices(sso.getUserInfoUri(), client.getClientId());
}
}
diff --git a/src/main/java/org/springframework/cloud/cloudfoundry/oauth2/UserInfoTokenServices.java b/src/main/java/org/springframework/cloud/cloudfoundry/oauth2/UserInfoTokenServices.java
index 0f73bbc..16f5d84 100644
--- a/src/main/java/org/springframework/cloud/cloudfoundry/oauth2/UserInfoTokenServices.java
+++ b/src/main/java/org/springframework/cloud/cloudfoundry/oauth2/UserInfoTokenServices.java
@@ -22,12 +22,14 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.authority.AuthorityUtils;
+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.web.client.RestOperations;
/**
* @author Dave Syer
@@ -37,15 +39,11 @@ public class UserInfoTokenServices implements ResourceServerTokenServices {
protected final Log logger = LogFactory.getLog(getClass());
- private RestOperations restTemplate;
-
private String userInfoEndpointUrl;
private String clientId;
- public UserInfoTokenServices(RestOperations restTemplate,
- String userInfoEndpointUrl, String clientId) {
- this.restTemplate = restTemplate;
+ public UserInfoTokenServices(String userInfoEndpointUrl, String clientId) {
this.userInfoEndpointUrl = userInfoEndpointUrl;
this.clientId = clientId;
}
@@ -54,7 +52,7 @@ public class UserInfoTokenServices implements ResourceServerTokenServices {
public OAuth2Authentication loadAuthentication(String accessToken)
throws AuthenticationException, InvalidTokenException {
- Map map = getMap(userInfoEndpointUrl);
+ Map map = getMap(userInfoEndpointUrl, accessToken);
if (map.containsKey("error")) {
logger.debug("userinfo returned error: " + map.get("error"));
@@ -90,11 +88,17 @@ public class UserInfoTokenServices implements ResourceServerTokenServices {
throw new UnsupportedOperationException("Not supported: read access token");
}
- private Map getMap(String path) {
+ private Map getMap(String path, String accessToken) {
+ logger.info("Getting user info from :" + path);
+ BaseOAuth2ProtectedResourceDetails resource = new BaseOAuth2ProtectedResourceDetails();
+ resource.setClientId(clientId);
+ OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(resource);
+ restTemplate.getOAuth2ClientContext().setAccessToken(new DefaultOAuth2AccessToken(accessToken));
@SuppressWarnings("rawtypes")
Map map = restTemplate.getForEntity(path, Map.class).getBody();
@SuppressWarnings("unchecked")
Map result = map;
return result;
}
+
}
\ No newline at end of file
diff --git a/src/main/java/org/springframework/cloud/cloudfoundry/resource/OAuth2ResourceConfiguration.java b/src/main/java/org/springframework/cloud/cloudfoundry/resource/OAuth2ResourceConfiguration.java
index 10a4ab9..318172a 100644
--- a/src/main/java/org/springframework/cloud/cloudfoundry/resource/OAuth2ResourceConfiguration.java
+++ b/src/main/java/org/springframework/cloud/cloudfoundry/resource/OAuth2ResourceConfiguration.java
@@ -42,7 +42,7 @@ import org.springframework.util.ClassUtils;
*
*/
@Configuration
-@ConditionalOnExpression("'${oauth2.resource.clientId:${vcap.services.resource.credentials.clientId:}}'!=''")
+@ConditionalOnExpression("'${oauth2.client.clientId:${vcap.services.resource.credentials.clientId:}}'!=''")
@ConditionalOnClass({ EnableResourceServer.class, SecurityProperties.class })
@ConditionalOnWebApplication
@EnableResourceServer
diff --git a/src/main/java/org/springframework/cloud/cloudfoundry/sso/OAuth2SsoConfiguration.java b/src/main/java/org/springframework/cloud/cloudfoundry/sso/OAuth2SsoConfiguration.java
index bb2b8d1..bd687cf 100644
--- a/src/main/java/org/springframework/cloud/cloudfoundry/sso/OAuth2SsoConfiguration.java
+++ b/src/main/java/org/springframework/cloud/cloudfoundry/sso/OAuth2SsoConfiguration.java
@@ -16,11 +16,9 @@
package org.springframework.cloud.cloudfoundry.sso;
import java.io.IOException;
-import java.util.Arrays;
import java.util.Collections;
import java.util.List;
-import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -31,214 +29,126 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
-import org.springframework.boot.context.embedded.FilterRegistrationBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.cloudfoundry.oauth2.ResourceServerTokenServicesConfiguration;
-import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
-import org.springframework.context.annotation.Scope;
-import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.core.Ordered;
-import org.springframework.http.HttpHeaders;
-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.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.core.Authentication;
-import org.springframework.security.oauth2.client.DefaultOAuth2ClientContext;
-import org.springframework.security.oauth2.client.OAuth2ClientContext;
import org.springframework.security.oauth2.client.OAuth2RestOperations;
-import org.springframework.security.oauth2.client.OAuth2RestTemplate;
import org.springframework.security.oauth2.client.filter.OAuth2ClientAuthenticationProcessingFilter;
-import org.springframework.security.oauth2.client.filter.OAuth2ClientContextFilter;
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.client.token.grant.code.AuthorizationCodeAccessTokenProvider;
-import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails;
-import org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client;
import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.util.ClassUtils;
-import org.springframework.util.MultiValueMap;
/**
* @author Dave Syer
*
*/
@Configuration
-@ConditionalOnExpression("'${oauth2.sso.clientId:${vcap.services.sso.credentials.clientId:}}'!=''")
-@ConditionalOnClass({ EnableOAuth2Client.class, SecurityProperties.class })
+@ConditionalOnExpression("'${oauth2.client.clientId:${vcap.services.sso.credentials.clientId:}}'!=''")
+@ConditionalOnClass({ ResourceServerTokenServices.class, SecurityProperties.class })
@ConditionalOnWebApplication
-@EnableOAuth2Client
@EnableConfigurationProperties(OAuth2SsoProperties.class)
@Import(ResourceServerTokenServicesConfiguration.class)
-public class OAuth2SsoConfiguration {
+public class OAuth2SsoConfiguration extends WebSecurityConfigurerAdapter implements Ordered {
+
+ @Autowired
+ private OAuth2ProtectedResourceDetails remote;
@Autowired
private OAuth2SsoProperties sso;
- @Resource
- @Qualifier("accessTokenRequest")
- private AccessTokenRequest accessTokenRequest;
+ @Autowired
+ private ResourceServerTokenServices tokenServices;
- @Bean
- public FilterRegistrationBean oauth2ClientFilterRegistration(
- OAuth2ClientContextFilter filter) {
- FilterRegistrationBean registration = new FilterRegistrationBean();
- registration.setFilter(filter);
- registration.setOrder(0);
- return registration;
+ @Autowired
+ @Qualifier("oauth2RestTemplate")
+ private OAuth2RestOperations restTemplate;
+
+ private List configurers = Collections.emptyList();
+
+ @Override
+ public int getOrder() {
+ if (ClassUtils
+ .isPresent(
+ "org.springframework.boot.actuate.autoconfigure.ManagementServerProperties",
+ null)) {
+ return ManagementServerProperties.ACCESS_OVERRIDE_ORDER;
+ }
+ return SecurityProperties.ACCESS_OVERRIDE_ORDER;
}
- @Bean
- public OAuth2ProtectedResourceDetails oauth2RemoteResource() {
- AuthorizationCodeResourceDetails details = new AuthorizationCodeResourceDetails();
- // set up resource details, OAuth2 URLs etc.
- details.setClientId(sso.getClientId());
- details.setClientSecret(sso.getClientSecret());
- details.setAccessTokenUri(sso.getTokenUri());
- details.setUserAuthorizationUri(sso.getAuthorizationUri());
- details.setClientAuthenticationScheme(sso.getAuthenticationScheme());
- return details;
+ /**
+ * @param configurers the configurers to set
+ */
+ @Autowired(required = false)
+ public void setConfigurers(List configurers) {
+ this.configurers = configurers;
}
- @Bean
- public OAuth2RestOperations oauth2RestTemplate() {
- OAuth2RestTemplate template = new OAuth2RestTemplate(oauth2RemoteResource(),
- oauth2ClientContext());
- template.setInterceptors(Arrays
- . asList(new 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);
- }
- }));
- AuthorizationCodeAccessTokenProvider accessTokenProvider = new AuthorizationCodeAccessTokenProvider();
- accessTokenProvider.setTokenRequestEnhancer(new RequestEnhancer() {
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+
+ http.addFilterAfter(cloudfoundrySsoFilter(),
+ AbstractPreAuthenticatedProcessingFilter.class);
+
+ for (OAuth2SsoConfigurer configurer : configurers) {
+ // Delegates can add authorizeRequests() here
+ configurer.configure(http);
+ }
+ if (configurers.isEmpty()) {
+ // Add anyRequest() last as a fall back. Spring Security would replace an
+ // existing anyRequest() matcher with this one, so to avoid that we only
+ // add it if the user hasn't configured anything.
+ ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry requests = http
+ .antMatcher("/**").authorizeRequests();
+ if (!sso.getHome().isSecure()) {
+ requests.antMatchers(sso.getHome().getPath()).permitAll();
+ }
+ requests.anyRequest().authenticated();
+ }
+
+ http.logout()
+ .logoutRequestMatcher(new AntPathRequestMatcher(sso.getLogoutPath()))
+ .addLogoutHandler(logoutHandler()).permitAll();
+ http.exceptionHandling().authenticationEntryPoint(
+ new LoginUrlAuthenticationEntryPoint(sso.getLoginPath()));
+
+ }
+
+ protected OAuth2ClientAuthenticationProcessingFilter cloudfoundrySsoFilter() {
+ OAuth2ClientAuthenticationProcessingFilter filter = new OAuth2ClientAuthenticationProcessingFilter(
+ sso.getLoginPath());
+ filter.setRestTemplate(restTemplate);
+ filter.setTokenServices(tokenServices);
+ return filter;
+ }
+
+ private LogoutHandler logoutHandler() {
+ LogoutHandler handler = new LogoutHandler() {
@Override
- public void enhance(AccessTokenRequest request,
- OAuth2ProtectedResourceDetails resource,
- MultiValueMap form, HttpHeaders headers) {
- headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
- }
- });
- template.setAccessTokenProvider(accessTokenProvider);
- return template;
- }
-
- @Bean
- @Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES)
- public OAuth2ClientContext oauth2ClientContext() {
- return new DefaultOAuth2ClientContext(accessTokenRequest);
- }
-
- @Configuration
- protected static class SsoSecurityConfigurer extends WebSecurityConfigurerAdapter
- implements Ordered {
-
- @Autowired
- private OAuth2ProtectedResourceDetails remote;
-
- @Autowired
- private OAuth2SsoProperties sso;
-
- @Autowired
- private ResourceServerTokenServices tokenServices;
-
- @Autowired
- @Qualifier("oauth2RestTemplate")
- private OAuth2RestOperations restTemplate;
-
- private List configurers = Collections.emptyList();
-
- @Override
- public int getOrder() {
- if (ClassUtils
- .isPresent(
- "org.springframework.boot.actuate.autoconfigure.ManagementServerProperties",
- null)) {
- return ManagementServerProperties.ACCESS_OVERRIDE_ORDER;
- }
- return SecurityProperties.ACCESS_OVERRIDE_ORDER;
- }
-
- /**
- * @param configurers the configurers to set
- */
- @Autowired(required = false)
- public void setConfigurers(List configurers) {
- this.configurers = configurers;
- }
-
- @Override
- protected void configure(HttpSecurity http) throws Exception {
-
- http.addFilterAfter(cloudfoundrySsoFilter(),
- AbstractPreAuthenticatedProcessingFilter.class);
-
- for (OAuth2SsoConfigurer configurer : configurers) {
- // Delegates can add authorizeRequests() here
- configurer.configure(http);
- }
- if (configurers.isEmpty()) {
- // Add anyRequest() last as a fall back. Spring Security would replace an
- // existing anyRequest() matcher with this one, so to avoid that we only
- // add it if the user hasn't configured anything.
- ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry requests = http
- .antMatcher("/**").authorizeRequests();
- if (!sso.getHome().isSecure()) {
- requests.antMatchers(sso.getHome().getPath()).permitAll();
+ public void logout(HttpServletRequest request, HttpServletResponse response,
+ Authentication authentication) {
+ restTemplate.getOAuth2ClientContext().setAccessToken(null);
+ String redirect = request.getRequestURL().toString()
+ .replace(sso.getLogoutPath(), sso.getHome().getPath());
+ try {
+ response.sendRedirect(sso.getLogoutUri(redirect));
}
- requests.anyRequest().authenticated();
- }
-
- http.logout()
- .logoutRequestMatcher(new AntPathRequestMatcher(sso.getLogoutPath()))
- .addLogoutHandler(logoutHandler()).permitAll();
- http.exceptionHandling().authenticationEntryPoint(
- new LoginUrlAuthenticationEntryPoint(sso.getLoginPath()));
-
- }
-
- protected OAuth2ClientAuthenticationProcessingFilter cloudfoundrySsoFilter() {
- OAuth2ClientAuthenticationProcessingFilter filter = new OAuth2ClientAuthenticationProcessingFilter(
- sso.getLoginPath());
- filter.setRestTemplate(restTemplate);
- filter.setTokenServices(tokenServices);
- return filter;
- }
-
- private LogoutHandler logoutHandler() {
- LogoutHandler handler = new LogoutHandler() {
- @Override
- public void logout(HttpServletRequest request,
- HttpServletResponse response, Authentication authentication) {
- restTemplate.getOAuth2ClientContext().setAccessToken(null);
- String redirect = request.getRequestURL().toString()
- .replace(sso.getLogoutPath(), sso.getHome().getPath());
- try {
- response.sendRedirect(sso.getLogoutUri(redirect));
- }
- catch (IOException e) {
- throw new IllegalStateException("Cannot logout remote server", e);
- }
+ catch (IOException e) {
+ throw new IllegalStateException("Cannot logout remote server", e);
}
- };
- return handler;
- }
-
+ }
+ };
+ return handler;
}
}
diff --git a/src/main/java/org/springframework/cloud/cloudfoundry/sso/OAuth2SsoProperties.java b/src/main/java/org/springframework/cloud/cloudfoundry/sso/OAuth2SsoProperties.java
index 239aba2..18735f4 100644
--- a/src/main/java/org/springframework/cloud/cloudfoundry/sso/OAuth2SsoProperties.java
+++ b/src/main/java/org/springframework/cloud/cloudfoundry/sso/OAuth2SsoProperties.java
@@ -16,13 +16,13 @@
package org.springframework.cloud.cloudfoundry.sso;
import lombok.Data;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.security.oauth2.common.AuthenticationScheme;
+import org.springframework.cloud.cloudfoundry.oauth2.OAuth2ClientProperties;
import org.springframework.util.StringUtils;
-import org.springframework.validation.Errors;
-import org.springframework.validation.Validator;
/**
* @author Dave Syer
@@ -30,7 +30,10 @@ import org.springframework.validation.Validator;
*/
@ConfigurationProperties("oauth2.sso")
@Data
-public class OAuth2SsoProperties implements Validator {
+@RequiredArgsConstructor(onConstructor = @__(@Autowired))
+public class OAuth2SsoProperties {
+
+ private final OAuth2ClientProperties client;
private String serviceId = "sso";
@@ -41,20 +44,6 @@ public class OAuth2SsoProperties implements Validator {
private String loginPath = "/login";
- @Value("${vcap.services.${oauth2.sso.serviceId:sso}.credentials.tokenUri:}")
- private String tokenUri;
-
- @Value("${vcap.services.${oauth2.sso.serviceId:sso}.credentials.authorizationUri:}")
- private String authorizationUri;
-
- @Value("${vcap.services.${oauth2.sso.serviceId:sso}.credentials.clientId:}")
- private String clientId;
-
- @Value("${vcap.services.${oauth2.sso.serviceId:sso}.credentials.clientSecret:}")
- private String clientSecret;
-
- private AuthenticationScheme authenticationScheme = AuthenticationScheme.header;
-
private Home home = new Home();
@Data
@@ -64,31 +53,8 @@ public class OAuth2SsoProperties implements Validator {
}
public String getLogoutUri(String redirectUrl) {
- return StringUtils.hasText(logoutUri) ? logoutUri : tokenUri.replace("/oauth/token",
+ return StringUtils.hasText(logoutUri) ? logoutUri : client.getTokenUri().replace("/oauth/token",
"/logout.do?redirect=" + redirectUrl);
}
- @Override
- public boolean supports(Class> clazz) {
- return OAuth2SsoProperties.class.isAssignableFrom(clazz);
- }
-
- @Override
- public void validate(Object target, Errors errors) {
- OAuth2SsoProperties sso = (OAuth2SsoProperties) target;
- if (StringUtils.hasText(sso.getClientId())) {
- if (!StringUtils.hasText(sso.getAuthorizationUri())) {
- errors.rejectValue("authorizeUri", "missing.authorizeUri",
- "Missing authorizeUri");
- }
- if (!StringUtils.hasText(sso.getTokenUri())) {
- errors.rejectValue("tokenUri", "missing.tokenUri", "Missing tokenUri");
- }
- if (!StringUtils.hasText(sso.getClientSecret())) {
- errors.rejectValue("clientSecret", "missing.clientSecret",
- "Missing clientSecret");
- }
- }
- }
-
}