From db9bfb0b56235ef05de1d6e6c59a909ada7df71e Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Mon, 1 Sep 2014 08:17:23 +0100 Subject: [PATCH] @EnableOAuth2* --- pom.xml | 9 +- .../ServiceBrokerAutoConfiguration.java | 20 ++-- .../oauth2/ResourceServerProperties.java | 52 +++++++++ ...ourceServerTokenServicesConfiguration.java | 108 ++++++++++++++++++ .../oauth2/SpringSocialTokenServices.java | 76 ++++++++++++ .../oauth2/UserInfoTokenServices.java | 100 ++++++++++++++++ ...java => OAuth2ProxyAutoConfiguration.java} | 6 +- ...okenFilter.java => OAuth2TokenFilter.java} | 2 +- .../CloudfoundryResourceProperties.java | 69 ----------- ...esource.java => EnableOAuth2Resource.java} | 4 +- ....java => OAuth2ResourceConfiguration.java} | 30 ++--- .../sso/EnableCloudfoundrySso.java | 4 +- .../cloudfoundry/sso/EnableOAuth2Sso.java | 36 ++++++ ...ation.java => OAuth2SsoConfiguration.java} | 76 ++++++++---- ...nfigurer.java => OAuth2SsoConfigurer.java} | 2 +- ...r.java => OAuth2SsoConfigurerAdapter.java} | 2 +- ...operties.java => OAuth2SsoProperties.java} | 44 +++---- src/main/resources/META-INF/spring.factories | 2 +- .../broker/sample/Application.java | 14 ++- src/test/resources/application.yml | 32 ++++-- 20 files changed, 511 insertions(+), 177 deletions(-) create mode 100644 src/main/java/org/springframework/cloud/cloudfoundry/oauth2/ResourceServerProperties.java create mode 100644 src/main/java/org/springframework/cloud/cloudfoundry/oauth2/ResourceServerTokenServicesConfiguration.java create mode 100644 src/main/java/org/springframework/cloud/cloudfoundry/oauth2/SpringSocialTokenServices.java create mode 100644 src/main/java/org/springframework/cloud/cloudfoundry/oauth2/UserInfoTokenServices.java rename src/main/java/org/springframework/cloud/cloudfoundry/proxy/{CloudfoundryProxyConfiguration.java => OAuth2ProxyAutoConfiguration.java} (90%) rename src/main/java/org/springframework/cloud/cloudfoundry/proxy/{CloudfoundryTokenFilter.java => OAuth2TokenFilter.java} (96%) delete mode 100644 src/main/java/org/springframework/cloud/cloudfoundry/resource/CloudfoundryResourceProperties.java rename src/main/java/org/springframework/cloud/cloudfoundry/resource/{EnableCloudfoundryResource.java => EnableOAuth2Resource.java} (91%) rename src/main/java/org/springframework/cloud/cloudfoundry/resource/{CloudfoundryResourceConfiguration.java => OAuth2ResourceConfiguration.java} (78%) create mode 100644 src/main/java/org/springframework/cloud/cloudfoundry/sso/EnableOAuth2Sso.java rename src/main/java/org/springframework/cloud/cloudfoundry/sso/{CloudfoundrySsoConfiguration.java => OAuth2SsoConfiguration.java} (72%) rename src/main/java/org/springframework/cloud/cloudfoundry/sso/{CloudfoundrySsoConfigurer.java => OAuth2SsoConfigurer.java} (94%) rename src/main/java/org/springframework/cloud/cloudfoundry/sso/{CloudfoundrySsoConfigurerAdapter.java => OAuth2SsoConfigurerAdapter.java} (90%) rename src/main/java/org/springframework/cloud/cloudfoundry/sso/{CloudfoundrySsoProperties.java => OAuth2SsoProperties.java} (64%) diff --git a/pom.xml b/pom.xml index 03cc1db..79fe022 100644 --- a/pom.xml +++ b/pom.xml @@ -62,6 +62,10 @@ 2.0.3.RELEASE true + + org.springframework.social + spring-social-core + org.projectlombok lombok @@ -82,11 +86,6 @@ spring-boot-starter-test test - - org.apache.ant - ant-launcher - 1.9.3 - diff --git a/src/main/java/org/springframework/cloud/cloudfoundry/broker/configuration/ServiceBrokerAutoConfiguration.java b/src/main/java/org/springframework/cloud/cloudfoundry/broker/configuration/ServiceBrokerAutoConfiguration.java index e03b402..691eb68 100644 --- a/src/main/java/org/springframework/cloud/cloudfoundry/broker/configuration/ServiceBrokerAutoConfiguration.java +++ b/src/main/java/org/springframework/cloud/cloudfoundry/broker/configuration/ServiceBrokerAutoConfiguration.java @@ -30,17 +30,12 @@ import org.cloudfoundry.community.servicebroker.service.ServiceInstanceService; import org.springframework.aop.framework.ProxyFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +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.ConditionalOnWebApplication; import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationListener; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.FilterType; import org.springframework.cloud.cloudfoundry.broker.FreeServiceDefinitionFactory; import org.springframework.cloud.cloudfoundry.broker.ServiceInstanceBindingRepository; import org.springframework.cloud.cloudfoundry.broker.ServiceInstanceRepository; @@ -50,6 +45,12 @@ import org.springframework.cloud.cloudfoundry.broker.simple.SimpleServiceInstanc import org.springframework.cloud.cloudfoundry.broker.simple.SimpleServiceInstanceService; import org.springframework.cloud.netflix.eureka.advice.PiggybackMethodInterceptor; import org.springframework.cloud.netflix.eureka.event.EurekaRegistryAvailableEvent; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationListener; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.FilterType; import org.springframework.stereotype.Component; import org.springframework.util.ReflectionUtils; @@ -83,14 +84,14 @@ import com.netflix.eureka.lease.LeaseManager; public class ServiceBrokerAutoConfiguration { @Configuration - @ConditionalOnMissingClass(name = "com.netflix.eureka.PeerAwareInstanceRegistry") - @ConditionalOnMissingBean(CatalogService.class) + @ConditionalOnMissingBean(EurekaInstanceConfig.class) protected static class CatalogConfiguration { @Autowired private BrokerProperties broker; @Bean + @ConditionalOnMissingBean(CatalogService.class) public BeanCatalogService catalogService() { return new BeanCatalogService(catalog()); } @@ -143,7 +144,7 @@ public class ServiceBrokerAutoConfiguration { } @Configuration - @ConditionalOnClass(PeerAwareInstanceRegistry.class) + @ConditionalOnBean(EurekaInstanceConfig.class) protected static class EurekaCatalogConfiguration { @Bean @@ -156,6 +157,7 @@ public class ServiceBrokerAutoConfiguration { @Configuration @ConditionalOnClass(PeerAwareInstanceRegistry.class) + @ConditionalOnBean(EurekaInstanceConfig.class) protected static class Initializer implements ApplicationListener { diff --git a/src/main/java/org/springframework/cloud/cloudfoundry/oauth2/ResourceServerProperties.java b/src/main/java/org/springframework/cloud/cloudfoundry/oauth2/ResourceServerProperties.java new file mode 100644 index 0000000..6100861 --- /dev/null +++ b/src/main/java/org/springframework/cloud/cloudfoundry/oauth2/ResourceServerProperties.java @@ -0,0 +1,52 @@ +/* + * 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; + +/** + * @author Dave Syer + * + */ +@ConfigurationProperties("oauth2.resource") +@Data +public class ResourceServerProperties { + + private String serviceId = "resource"; + + private String id; + + @Value("${vcap.services.${oauth2.resource.serviceId:resource}.credentials.clientId:}") + private String clientId; + + @Value("${vcap.services.${oauth2.resource.serviceId:resource}.credentials.clientSecret:}") + private String clientSecret; + + @Value("${vcap.services.${oauth2.resource.serviceId:sso}.credentials.userInfoUri:}") + private String userInfoUri; + + @Value("${vcap.services.${oauth2.resource.serviceId:sso}.credentials.tokenInfoUri:}") + private String tokenInfoUri; + + private boolean preferTokenInfo = true; + + public String getResourceId() { + return id==null ? clientId : id; + } +} diff --git a/src/main/java/org/springframework/cloud/cloudfoundry/oauth2/ResourceServerTokenServicesConfiguration.java b/src/main/java/org/springframework/cloud/cloudfoundry/oauth2/ResourceServerTokenServicesConfiguration.java new file mode 100644 index 0000000..42a8e11 --- /dev/null +++ b/src/main/java/org/springframework/cloud/cloudfoundry/oauth2/ResourceServerTokenServicesConfiguration.java @@ -0,0 +1,108 @@ +/* + * 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 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; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass; +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.security.oauth2.provider.token.RemoteTokenServices; +import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices; +import org.springframework.social.connect.support.OAuth2ConnectionFactory; + +/** + * @author Dave Syer + * + */ +@Configuration +@EnableConfigurationProperties(ResourceServerProperties.class) +public class ResourceServerTokenServicesConfiguration { + + @Autowired + private ResourceServerProperties resource; + + @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()); + return services; + } + + @Configuration + @ConditionalOnClass(OAuth2ConnectionFactory.class) + @ConditionalOnExpression("!${oauth2.resource.preferTokenInfo:${OAUTH2_RESOURCE_PREFERTOKENINFO:true}}") + protected static class SocialTokenServicesConfiguration { + + @Autowired + private ResourceServerProperties sso; + + @Autowired(required = false) + private OAuth2ConnectionFactory connectionFactory; + + @Autowired(required = false) + @Qualifier("oauth2RestTemplate") + private OAuth2RestOperations restTemplate; + + @Bean + @ConditionalOnBean(OAuth2ConnectionFactory.class) + @ConditionalOnMissingBean(ResourceServerTokenServices.class) + public SpringSocialTokenServices socialTokenServices() { + return new SpringSocialTokenServices(connectionFactory, sso.getClientId()); + } + + @Bean + @ConditionalOnMissingBean({ OAuth2ConnectionFactory.class, + ResourceServerTokenServices.class }) + public UserInfoTokenServices userInfoTokenServices() { + return new UserInfoTokenServices(restTemplate, sso.getUserInfoUri(), + sso.getClientId()); + } + + } + + @Configuration + @ConditionalOnMissingClass(name = "org.springframework.social.connect.support.OAuth2ConnectionFactory") + @ConditionalOnExpression("!${oauth2.resource.preferTokenInfo:${OAUTH2_RESOURCE_PREFERTOKENINFO:true}}") + protected static class UserInfoTokenServicesConfiguration { + + @Autowired + private ResourceServerProperties sso; + + @Autowired + @Qualifier("oauth2RestTemplate") + private OAuth2RestOperations restTemplate; + + @Bean + @ConditionalOnMissingBean(ResourceServerTokenServices.class) + public UserInfoTokenServices userInfoTokenServices() { + return new UserInfoTokenServices(restTemplate, sso.getUserInfoUri(), + sso.getClientId()); + } + + } + +} diff --git a/src/main/java/org/springframework/cloud/cloudfoundry/oauth2/SpringSocialTokenServices.java b/src/main/java/org/springframework/cloud/cloudfoundry/oauth2/SpringSocialTokenServices.java new file mode 100644 index 0000000..49f258c --- /dev/null +++ b/src/main/java/org/springframework/cloud/cloudfoundry/oauth2/SpringSocialTokenServices.java @@ -0,0 +1,76 @@ +/* + * 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 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.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; + +/** + * @author Dave Syer + * + */ +public class SpringSocialTokenServices implements ResourceServerTokenServices { + + protected final Log logger = LogFactory.getLog(getClass()); + + private OAuth2ConnectionFactory connectionFactory; + + private String clientId; + + public SpringSocialTokenServices(OAuth2ConnectionFactory connectionFactory, + String clientId) { + this.connectionFactory = connectionFactory; + this.clientId = clientId; + } + + @Override + public OAuth2Authentication loadAuthentication(String accessToken) + throws AuthenticationException, InvalidTokenException { + + Connection connection = connectionFactory.createConnection(new AccessGrant( + accessToken)); + UserProfile user = connection.fetchUserProfile(); + return extractAuthentication(user); + } + + private OAuth2Authentication extractAuthentication(UserProfile user) { + UsernamePasswordAuthenticationToken principal = new UsernamePasswordAuthenticationToken( + user.getUsername(), "N/A", + AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER")); + principal.setDetails(user); + OAuth2Request request = new OAuth2Request(null, clientId, null, true, null, null, + null, null, null); + return new OAuth2Authentication(request, principal); + } + + @Override + public OAuth2AccessToken readAccessToken(String accessToken) { + throw new UnsupportedOperationException("Not supported: read access token"); + } + +} \ No newline at end of file diff --git a/src/main/java/org/springframework/cloud/cloudfoundry/oauth2/UserInfoTokenServices.java b/src/main/java/org/springframework/cloud/cloudfoundry/oauth2/UserInfoTokenServices.java new file mode 100644 index 0000000..0f73bbc --- /dev/null +++ b/src/main/java/org/springframework/cloud/cloudfoundry/oauth2/UserInfoTokenServices.java @@ -0,0 +1,100 @@ +/* + * 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.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.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.web.client.RestOperations; + +/** + * @author Dave Syer + * + */ +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; + this.userInfoEndpointUrl = userInfoEndpointUrl; + this.clientId = clientId; + } + + @Override + public OAuth2Authentication loadAuthentication(String accessToken) + throws AuthenticationException, InvalidTokenException { + + Map map = getMap(userInfoEndpointUrl); + + if (map.containsKey("error")) { + logger.debug("userinfo returned error: " + map.get("error")); + throw new InvalidTokenException(accessToken); + } + + return extractAuthentication(map); + } + + private OAuth2Authentication extractAuthentication(Map map) { + UsernamePasswordAuthenticationToken user = new UsernamePasswordAuthenticationToken( + getPrincipal(map), "N/A", + AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER")); + user.setDetails(map); + OAuth2Request request = new OAuth2Request(null, clientId, null, true, null, + null, null, null, null); + return new OAuth2Authentication(request, user); + } + + private Object getPrincipal(Map map) { + String[] keys = new String[] { "user", "username", "userid", "user_id", + "login", "id" }; + for (String key : keys) { + if (map.containsKey(key)) { + return map.get(key); + } + } + return "unknown"; + } + + @Override + public OAuth2AccessToken readAccessToken(String accessToken) { + throw new UnsupportedOperationException("Not supported: read access token"); + } + + private Map getMap(String path) { + @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/proxy/CloudfoundryProxyConfiguration.java b/src/main/java/org/springframework/cloud/cloudfoundry/proxy/OAuth2ProxyAutoConfiguration.java similarity index 90% rename from src/main/java/org/springframework/cloud/cloudfoundry/proxy/CloudfoundryProxyConfiguration.java rename to src/main/java/org/springframework/cloud/cloudfoundry/proxy/OAuth2ProxyAutoConfiguration.java index 469ef58..8ae4728 100644 --- a/src/main/java/org/springframework/cloud/cloudfoundry/proxy/CloudfoundryProxyConfiguration.java +++ b/src/main/java/org/springframework/cloud/cloudfoundry/proxy/OAuth2ProxyAutoConfiguration.java @@ -31,11 +31,11 @@ import com.netflix.zuul.ZuulFilter; @Configuration @ConditionalOnClass({ ZuulFilter.class, EnableOAuth2Client.class, SecurityProperties.class }) @ConditionalOnWebApplication -public class CloudfoundryProxyConfiguration { +public class OAuth2ProxyAutoConfiguration { @Bean - public CloudfoundryTokenFilter cloudfoundryTokenFilter() { - return new CloudfoundryTokenFilter(); + public OAuth2TokenFilter cloudfoundryTokenFilter() { + return new OAuth2TokenFilter(); } } diff --git a/src/main/java/org/springframework/cloud/cloudfoundry/proxy/CloudfoundryTokenFilter.java b/src/main/java/org/springframework/cloud/cloudfoundry/proxy/OAuth2TokenFilter.java similarity index 96% rename from src/main/java/org/springframework/cloud/cloudfoundry/proxy/CloudfoundryTokenFilter.java rename to src/main/java/org/springframework/cloud/cloudfoundry/proxy/OAuth2TokenFilter.java index dd3b4f9..973018e 100644 --- a/src/main/java/org/springframework/cloud/cloudfoundry/proxy/CloudfoundryTokenFilter.java +++ b/src/main/java/org/springframework/cloud/cloudfoundry/proxy/OAuth2TokenFilter.java @@ -8,7 +8,7 @@ import org.springframework.security.oauth2.provider.authentication.OAuth2Authent import com.netflix.zuul.ZuulFilter; import com.netflix.zuul.context.RequestContext; -public class CloudfoundryTokenFilter extends ZuulFilter { +public class OAuth2TokenFilter extends ZuulFilter { private static final String ACCESS_TOKEN = "ACCESS_TOKEN"; diff --git a/src/main/java/org/springframework/cloud/cloudfoundry/resource/CloudfoundryResourceProperties.java b/src/main/java/org/springframework/cloud/cloudfoundry/resource/CloudfoundryResourceProperties.java deleted file mode 100644 index a9047b4..0000000 --- a/src/main/java/org/springframework/cloud/cloudfoundry/resource/CloudfoundryResourceProperties.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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.resource; - -import lombok.Data; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.util.StringUtils; -import org.springframework.validation.Errors; -import org.springframework.validation.Validator; - -/** - * @author Dave Syer - * - */ -@ConfigurationProperties("cloudfoundry.resource") -@Data -public class CloudfoundryResourceProperties implements Validator { - - private String serviceId = "resource"; - - private String id; - - @Value("${vcap.services.${cloudfoundry.resource.serviceId:resource}.credentials.clientId:}") - private String clientId; - - @Value("${vcap.services.${cloudfoundry.resource.serviceId:resource}.credentials.clientSecret:}") - private String clientSecret; - - @Value("${vcap.services.${cloudfoundry.resource.serviceId:resource}.credentials.tokenInfoUri:}") - private String tokenInfoUri; - - - @Override - public boolean supports(Class clazz) { - return CloudfoundryResourceProperties.class.isAssignableFrom(clazz); - } - - @Override - public void validate(Object target, Errors errors) { - CloudfoundryResourceProperties resource = (CloudfoundryResourceProperties) target; - if (StringUtils.hasText(resource.getClientId())) { - if (!StringUtils.hasText(resource.getTokenInfoUri())) { - errors.rejectValue("tokenInfoUri", "missing.tokenInfoUri", "Missing tokenInfoUri"); - } - if (!StringUtils.hasText(resource.getClientSecret())) { - errors.rejectValue("clientSecret", "missing.clientSecret", "Missing clientSecret"); - } - } - } - - public String getResourceId() { - return id==null ? clientId : id; - } -} diff --git a/src/main/java/org/springframework/cloud/cloudfoundry/resource/EnableCloudfoundryResource.java b/src/main/java/org/springframework/cloud/cloudfoundry/resource/EnableOAuth2Resource.java similarity index 91% rename from src/main/java/org/springframework/cloud/cloudfoundry/resource/EnableCloudfoundryResource.java rename to src/main/java/org/springframework/cloud/cloudfoundry/resource/EnableOAuth2Resource.java index 21b0e55..23cca3c 100644 --- a/src/main/java/org/springframework/cloud/cloudfoundry/resource/EnableCloudfoundryResource.java +++ b/src/main/java/org/springframework/cloud/cloudfoundry/resource/EnableOAuth2Resource.java @@ -30,7 +30,7 @@ import org.springframework.context.annotation.Import; @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented -@Import(CloudfoundryResourceConfiguration.class) -public @interface EnableCloudfoundryResource { +@Import(OAuth2ResourceConfiguration.class) +public @interface EnableOAuth2Resource { } diff --git a/src/main/java/org/springframework/cloud/cloudfoundry/resource/CloudfoundryResourceConfiguration.java b/src/main/java/org/springframework/cloud/cloudfoundry/resource/OAuth2ResourceConfiguration.java similarity index 78% rename from src/main/java/org/springframework/cloud/cloudfoundry/resource/CloudfoundryResourceConfiguration.java rename to src/main/java/org/springframework/cloud/cloudfoundry/resource/OAuth2ResourceConfiguration.java index 0a33300..10a4ab9 100644 --- a/src/main/java/org/springframework/cloud/cloudfoundry/resource/CloudfoundryResourceConfiguration.java +++ b/src/main/java/org/springframework/cloud/cloudfoundry/resource/OAuth2ResourceConfiguration.java @@ -24,17 +24,17 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.security.SecurityProperties; -import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.cloud.cloudfoundry.oauth2.ResourceServerProperties; +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.security.config.annotation.web.builders.HttpSecurity; 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.security.oauth2.provider.token.RemoteTokenServices; -import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices; import org.springframework.util.ClassUtils; /** @@ -42,40 +42,28 @@ import org.springframework.util.ClassUtils; * */ @Configuration -@ConditionalOnExpression("'${cloudfoundry.resource.clientId:${vcap.services.resource.credentials.clientId:}}'!=''") +@ConditionalOnExpression("'${oauth2.resource.clientId:${vcap.services.resource.credentials.clientId:}}'!=''") @ConditionalOnClass({ EnableResourceServer.class, SecurityProperties.class }) @ConditionalOnWebApplication @EnableResourceServer -@EnableConfigurationProperties(CloudfoundryResourceProperties.class) -public class CloudfoundryResourceConfiguration { +@Import(ResourceServerTokenServicesConfiguration.class) +public class OAuth2ResourceConfiguration { @Autowired - private CloudfoundryResourceProperties resource; + private ResourceServerProperties resource; @Bean @ConditionalOnMissingBean(ResourceServerConfigurer.class) public ResourceServerConfigurer resourceServer() { return new ResourceSecurityConfigurer(resource); } - - @Bean - @ConditionalOnMissingBean(ResourceServerTokenServices.class) - public ResourceServerTokenServices tokenServices() { - RemoteTokenServices services = new RemoteTokenServices(); - services.setCheckTokenEndpointUrl(resource.getTokenInfoUri()); - services.setClientId(resource.getClientId()); - services.setClientSecret(resource.getClientSecret()); - return services; - } - - protected static class ResourceSecurityConfigurer extends ResourceServerConfigurerAdapter { - private CloudfoundryResourceProperties resource; + private ResourceServerProperties resource; @Autowired - public ResourceSecurityConfigurer(CloudfoundryResourceProperties resource) { + public ResourceSecurityConfigurer(ResourceServerProperties resource) { this.resource = resource; } diff --git a/src/main/java/org/springframework/cloud/cloudfoundry/sso/EnableCloudfoundrySso.java b/src/main/java/org/springframework/cloud/cloudfoundry/sso/EnableCloudfoundrySso.java index a6c7582..0c62cc4 100644 --- a/src/main/java/org/springframework/cloud/cloudfoundry/sso/EnableCloudfoundrySso.java +++ b/src/main/java/org/springframework/cloud/cloudfoundry/sso/EnableCloudfoundrySso.java @@ -21,8 +21,6 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import org.springframework.context.annotation.Import; - /** * @author Dave Syer * @@ -30,7 +28,7 @@ import org.springframework.context.annotation.Import; @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented -@Import(CloudfoundrySsoConfiguration.class) +@EnableOAuth2Sso public @interface EnableCloudfoundrySso { } diff --git a/src/main/java/org/springframework/cloud/cloudfoundry/sso/EnableOAuth2Sso.java b/src/main/java/org/springframework/cloud/cloudfoundry/sso/EnableOAuth2Sso.java new file mode 100644 index 0000000..1a81b9f --- /dev/null +++ b/src/main/java/org/springframework/cloud/cloudfoundry/sso/EnableOAuth2Sso.java @@ -0,0 +1,36 @@ +/* + * 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.sso; + +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.context.annotation.Import; + +/** + * @author Dave Syer + * + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Import(OAuth2SsoConfiguration.class) +public @interface EnableOAuth2Sso { + +} diff --git a/src/main/java/org/springframework/cloud/cloudfoundry/sso/CloudfoundrySsoConfiguration.java b/src/main/java/org/springframework/cloud/cloudfoundry/sso/OAuth2SsoConfiguration.java similarity index 72% rename from src/main/java/org/springframework/cloud/cloudfoundry/sso/CloudfoundrySsoConfiguration.java rename to src/main/java/org/springframework/cloud/cloudfoundry/sso/OAuth2SsoConfiguration.java index b1ea730..21a0f03 100644 --- a/src/main/java/org/springframework/cloud/cloudfoundry/sso/CloudfoundrySsoConfiguration.java +++ b/src/main/java/org/springframework/cloud/cloudfoundry/sso/OAuth2SsoConfiguration.java @@ -16,6 +16,7 @@ package org.springframework.cloud.cloudfoundry.sso; import java.io.IOException; +import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -32,11 +33,19 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplicat 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; @@ -49,30 +58,33 @@ import org.springframework.security.oauth2.client.filter.OAuth2ClientAuthenticat 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.RemoteTokenServices; 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("'${cloudfoundry.sso.clientId:${vcap.services.sso.credentials.clientId:}}'!=''") +@ConditionalOnExpression("'${oauth2.sso.clientId:${vcap.services.sso.credentials.clientId:}}'!=''") @ConditionalOnClass({ EnableOAuth2Client.class, SecurityProperties.class }) @ConditionalOnWebApplication @EnableOAuth2Client -@EnableConfigurationProperties(CloudfoundrySsoProperties.class) -public class CloudfoundrySsoConfiguration { +@EnableConfigurationProperties(OAuth2SsoProperties.class) +@Import(ResourceServerTokenServicesConfiguration.class) +public class OAuth2SsoConfiguration { @Autowired - private CloudfoundrySsoProperties sso; + private OAuth2SsoProperties sso; @Resource @Qualifier("accessTokenRequest") @@ -88,19 +100,42 @@ public class CloudfoundrySsoConfiguration { } @Bean - public OAuth2ProtectedResourceDetails remote() { + 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 restTemplate() { - return new OAuth2RestTemplate(remote(), oauth2ClientContext()); + 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 @@ -117,12 +152,16 @@ public class CloudfoundrySsoConfiguration { private OAuth2ProtectedResourceDetails remote; @Autowired - private CloudfoundrySsoProperties sso; + private OAuth2SsoProperties sso; @Autowired + private ResourceServerTokenServices tokenServices; + + @Autowired + @Qualifier("oauth2RestTemplate") private OAuth2RestOperations restTemplate; - private List configurers = Collections.emptyList(); + private List configurers = Collections.emptyList(); @Override public int getOrder() { @@ -139,7 +178,7 @@ public class CloudfoundrySsoConfiguration { * @param configurers the configurers to set */ @Autowired(required = false) - public void setConfigurers(List configurers) { + public void setConfigurers(List configurers) { this.configurers = configurers; } @@ -149,7 +188,7 @@ public class CloudfoundrySsoConfiguration { http.addFilterAfter(cloudfoundrySsoFilter(), AbstractPreAuthenticatedProcessingFilter.class); - for (CloudfoundrySsoConfigurer configurer : configurers) { + for (OAuth2SsoConfigurer configurer : configurers) { // Delegates can add authorizeRequests() here configurer.configure(http); } @@ -165,7 +204,8 @@ public class CloudfoundrySsoConfiguration { requests.anyRequest().authenticated(); } - http.logout().logoutRequestMatcher(new AntPathRequestMatcher(sso.getLogoutPath())) + http.logout() + .logoutRequestMatcher(new AntPathRequestMatcher(sso.getLogoutPath())) .addLogoutHandler(logoutHandler()); http.exceptionHandling().authenticationEntryPoint( new LoginUrlAuthenticationEntryPoint(sso.getLoginPath())); @@ -176,18 +216,10 @@ public class CloudfoundrySsoConfiguration { OAuth2ClientAuthenticationProcessingFilter filter = new OAuth2ClientAuthenticationProcessingFilter( sso.getLoginPath()); filter.setRestTemplate(restTemplate); - filter.setTokenServices(tokenServices()); + filter.setTokenServices(tokenServices); return filter; } - private ResourceServerTokenServices tokenServices() { - RemoteTokenServices services = new RemoteTokenServices(); - services.setCheckTokenEndpointUrl(sso.getTokenInfoUri()); - services.setClientId(sso.getClientId()); - services.setClientSecret(sso.getClientSecret()); - return services; - } - private LogoutHandler logoutHandler() { LogoutHandler handler = new LogoutHandler() { @Override diff --git a/src/main/java/org/springframework/cloud/cloudfoundry/sso/CloudfoundrySsoConfigurer.java b/src/main/java/org/springframework/cloud/cloudfoundry/sso/OAuth2SsoConfigurer.java similarity index 94% rename from src/main/java/org/springframework/cloud/cloudfoundry/sso/CloudfoundrySsoConfigurer.java rename to src/main/java/org/springframework/cloud/cloudfoundry/sso/OAuth2SsoConfigurer.java index 4888b4a..262ee2e 100644 --- a/src/main/java/org/springframework/cloud/cloudfoundry/sso/CloudfoundrySsoConfigurer.java +++ b/src/main/java/org/springframework/cloud/cloudfoundry/sso/OAuth2SsoConfigurer.java @@ -21,7 +21,7 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity; * @author Dave Syer * */ -public interface CloudfoundrySsoConfigurer { +public interface OAuth2SsoConfigurer { void configure(HttpSecurity http); diff --git a/src/main/java/org/springframework/cloud/cloudfoundry/sso/CloudfoundrySsoConfigurerAdapter.java b/src/main/java/org/springframework/cloud/cloudfoundry/sso/OAuth2SsoConfigurerAdapter.java similarity index 90% rename from src/main/java/org/springframework/cloud/cloudfoundry/sso/CloudfoundrySsoConfigurerAdapter.java rename to src/main/java/org/springframework/cloud/cloudfoundry/sso/OAuth2SsoConfigurerAdapter.java index 65f2241..9a9b99f 100644 --- a/src/main/java/org/springframework/cloud/cloudfoundry/sso/CloudfoundrySsoConfigurerAdapter.java +++ b/src/main/java/org/springframework/cloud/cloudfoundry/sso/OAuth2SsoConfigurerAdapter.java @@ -21,7 +21,7 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity; * @author Dave Syer * */ -public class CloudfoundrySsoConfigurerAdapter implements CloudfoundrySsoConfigurer { +public class OAuth2SsoConfigurerAdapter implements OAuth2SsoConfigurer { @Override public void configure(HttpSecurity http) { diff --git a/src/main/java/org/springframework/cloud/cloudfoundry/sso/CloudfoundrySsoProperties.java b/src/main/java/org/springframework/cloud/cloudfoundry/sso/OAuth2SsoProperties.java similarity index 64% rename from src/main/java/org/springframework/cloud/cloudfoundry/sso/CloudfoundrySsoProperties.java rename to src/main/java/org/springframework/cloud/cloudfoundry/sso/OAuth2SsoProperties.java index 7d4ff66..85d7982 100644 --- a/src/main/java/org/springframework/cloud/cloudfoundry/sso/CloudfoundrySsoProperties.java +++ b/src/main/java/org/springframework/cloud/cloudfoundry/sso/OAuth2SsoProperties.java @@ -19,6 +19,7 @@ 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; @@ -27,34 +28,33 @@ import org.springframework.validation.Validator; * @author Dave Syer * */ -@ConfigurationProperties("cloudfoundry.sso") +@ConfigurationProperties("oauth2.sso") @Data -public class CloudfoundrySsoProperties implements Validator { +public class OAuth2SsoProperties implements Validator { private String serviceId = "sso"; - + private String logoutPath = "/logout"; - + + @Value("${vcap.services.${oauth2.sso.serviceId:sso}.credentials.logoutUri:}") + private String logoutUri; + private String loginPath = "/login"; - @Value("${vcap.services.${cloudfoundry.sso.serviceId:sso}.credentials.tokenUri:}") + @Value("${vcap.services.${oauth2.sso.serviceId:sso}.credentials.tokenUri:}") private String tokenUri; - @Value("${vcap.services.${cloudfoundry.sso.serviceId:sso}.credentials.userInfoUri:}") - private String userInfoUri; - - @Value("${vcap.services.${cloudfoundry.sso.serviceId:sso}.credentials.tokenInfoUri:}") - private String tokenInfoUri; - - @Value("${vcap.services.${cloudfoundry.sso.serviceId:sso}.credentials.authorizationUri:}") + @Value("${vcap.services.${oauth2.sso.serviceId:sso}.credentials.authorizationUri:}") private String authorizationUri; - @Value("${vcap.services.${cloudfoundry.sso.serviceId:sso}.credentials.clientId:}") + @Value("${vcap.services.${oauth2.sso.serviceId:sso}.credentials.clientId:}") private String clientId; - @Value("${vcap.services.${cloudfoundry.sso.serviceId:sso}.credentials.clientSecret:}") + @Value("${vcap.services.${oauth2.sso.serviceId:sso}.credentials.clientSecret:}") private String clientSecret; + private AuthenticationScheme authenticationScheme = AuthenticationScheme.header; + private Home home = new Home(); @Data @@ -63,27 +63,19 @@ public class CloudfoundrySsoProperties implements Validator { private boolean secure = true; } - public String getTokenInfoUri() { - return StringUtils.hasText(tokenInfoUri) ? tokenInfoUri : tokenUri.replace( - "/oauth/token", "/check_token"); - } - - public String getUserInfoUri() { - return tokenUri.replace("/oauth/token", "/user_info"); - } - public String getLogoutUri(String redirectUrl) { - return tokenUri.replace("/oauth/token", "/logout.do?redirect=" + redirectUrl); + return logoutUri != null ? logoutUri : tokenUri.replace("/oauth/token", + "/logout.do?redirect=" + redirectUrl); } @Override public boolean supports(Class clazz) { - return CloudfoundrySsoProperties.class.isAssignableFrom(clazz); + return OAuth2SsoProperties.class.isAssignableFrom(clazz); } @Override public void validate(Object target, Errors errors) { - CloudfoundrySsoProperties sso = (CloudfoundrySsoProperties) target; + OAuth2SsoProperties sso = (OAuth2SsoProperties) target; if (StringUtils.hasText(sso.getClientId())) { if (!StringUtils.hasText(sso.getAuthorizationUri())) { errors.rejectValue("authorizeUri", "missing.authorizeUri", diff --git a/src/main/resources/META-INF/spring.factories b/src/main/resources/META-INF/spring.factories index dae2c26..c001fed 100644 --- a/src/main/resources/META-INF/spring.factories +++ b/src/main/resources/META-INF/spring.factories @@ -1,3 +1,3 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.cloud.cloudfoundry.broker.configuration.ServiceBrokerAutoConfiguration,\ -org.springframework.cloud.cloudfoundry.proxy.CloudfoundryProxyConfiguration \ No newline at end of file +org.springframework.cloud.cloudfoundry.proxy.OAuth2ProxyAutoConfiguration \ No newline at end of file diff --git a/src/test/java/org/springframework/cloud/cloudfoundry/broker/sample/Application.java b/src/test/java/org/springframework/cloud/cloudfoundry/broker/sample/Application.java index c251a77..a38afd4 100644 --- a/src/test/java/org/springframework/cloud/cloudfoundry/broker/sample/Application.java +++ b/src/test/java/org/springframework/cloud/cloudfoundry/broker/sample/Application.java @@ -15,15 +15,25 @@ */ package org.springframework.cloud.cloudfoundry.broker.sample; +import java.security.Principal; + import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.context.annotation.Configuration; -import org.springframework.cloud.cloudfoundry.sso.EnableCloudfoundrySso; +import org.springframework.cloud.cloudfoundry.sso.EnableOAuth2Sso; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; @Configuration @EnableAutoConfiguration -@EnableCloudfoundrySso +@EnableOAuth2Sso +@RestController public class Application { + + @RequestMapping("/") + public Principal home(Principal principal) { + return principal; + } public static void main(String[] args) { SpringApplication.run(Application.class, args); diff --git a/src/test/resources/application.yml b/src/test/resources/application.yml index 843114b..5cd0b12 100644 --- a/src/test/resources/application.yml +++ b/src/test/resources/application.yml @@ -1,12 +1,15 @@ debug: true server: - port: 8787 + port: 8080 spring: application: name: eureka management: context-path: /admin -cloudfoundry: +eureka: + server: + enabled: false +oauth2: sso: tokenUri: http://localhost:8080/uaa/oauth/token authorizationUri: http://localhost:8080/uaa/oauth/authorize @@ -16,12 +19,19 @@ logging: level: com.netflix.discovery: 'OFF' org.springframework.security: DEBUG -eureka: - server: - waitTimeInMsWhenSyncEmpty: 1000 - client: - serviceUrl: - defaultZone: http://localhost:8787/v2/ - default.defaultZone: http://localhost:8787/v2/ - registerWithEureka: false - fetchRegistry: false \ No newline at end of file + +--- +spring: + profiles: github +oauth2: + sso: + tokenUri: https://github.com/login/oauth/access_token + authorizationUri: https://github.com/login/oauth/authorize + clientId: bd1c0a783ccdd1c9b9e4 + clientSecret: 1a9030fbca47a5b2c28e92f19050bb77824b5ad1 + authenticationScheme: form + resource: + clientId: ${oauth2.sso.clientId} + userInfoUri: https://api.github.com/user + preferTokenInfo: false + \ No newline at end of file