diff --git a/pom.xml b/pom.xml
index 3d5e79f56..b05c742dc 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
OAuth for Spring Security
Parent Project for OAuth Support for Spring Security
pom
- 2.0.13.BUILD-SNAPSHOT
+ 2.1.1.BUILD-SNAPSHOT
http://static.springframework.org/spring-security/oauth
diff --git a/samples/oauth/sparklr/pom.xml b/samples/oauth/sparklr/pom.xml
index 4cc3debd2..d5985dc6d 100644
--- a/samples/oauth/sparklr/pom.xml
+++ b/samples/oauth/sparklr/pom.xml
@@ -5,7 +5,7 @@
org.springframework.security.oauth
spring-security-oauth-parent
- 2.0.13.BUILD-SNAPSHOT
+ 2.1.1.BUILD-SNAPSHOT
../../..
diff --git a/samples/oauth/tonr/pom.xml b/samples/oauth/tonr/pom.xml
index 570abf329..283337497 100644
--- a/samples/oauth/tonr/pom.xml
+++ b/samples/oauth/tonr/pom.xml
@@ -5,7 +5,7 @@
org.springframework.security.oauth
spring-security-oauth-parent
- 2.0.13.BUILD-SNAPSHOT
+ 2.1.1.BUILD-SNAPSHOT
../../..
diff --git a/samples/oauth2/sparklr/pom.xml b/samples/oauth2/sparklr/pom.xml
index fa285f8af..1f9013dd3 100644
--- a/samples/oauth2/sparklr/pom.xml
+++ b/samples/oauth2/sparklr/pom.xml
@@ -5,7 +5,7 @@
org.springframework.security.oauth
spring-security-oauth-parent
- 2.0.13.BUILD-SNAPSHOT
+ 2.1.1.BUILD-SNAPSHOT
../../..
diff --git a/samples/oauth2/tonr/pom.xml b/samples/oauth2/tonr/pom.xml
index 1131e00b1..50334a463 100644
--- a/samples/oauth2/tonr/pom.xml
+++ b/samples/oauth2/tonr/pom.xml
@@ -6,7 +6,7 @@
org.springframework.security.oauth
spring-security-oauth-parent
- 2.0.13.BUILD-SNAPSHOT
+ 2.1.1.BUILD-SNAPSHOT
../../..
diff --git a/samples/pom.xml b/samples/pom.xml
index 2c56b940a..96c07851c 100755
--- a/samples/pom.xml
+++ b/samples/pom.xml
@@ -4,7 +4,7 @@
org.springframework.security.oauth
spring-security-oauth-parent
- 2.0.13.BUILD-SNAPSHOT
+ 2.1.1.BUILD-SNAPSHOT
spring-security-oauth-samples
diff --git a/spring-security-oauth/pom.xml b/spring-security-oauth/pom.xml
index 7dd4a4c1d..587b63fac 100644
--- a/spring-security-oauth/pom.xml
+++ b/spring-security-oauth/pom.xml
@@ -4,7 +4,7 @@
org.springframework.security.oauth
spring-security-oauth-parent
- 2.0.13.BUILD-SNAPSHOT
+ 2.1.1.BUILD-SNAPSHOT
spring-security-oauth
diff --git a/spring-security-oauth2/pom.xml b/spring-security-oauth2/pom.xml
index 4949b5ba2..a850142f0 100644
--- a/spring-security-oauth2/pom.xml
+++ b/spring-security-oauth2/pom.xml
@@ -5,7 +5,7 @@
org.springframework.security.oauth
spring-security-oauth-parent
- 2.0.13.BUILD-SNAPSHOT
+ 2.1.1.BUILD-SNAPSHOT
spring-security-oauth2
diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerEndpointsConfiguration.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerEndpointsConfiguration.java
index 2fc3e63c2..160f7eb07 100644
--- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerEndpointsConfiguration.java
+++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configuration/AuthorizationServerEndpointsConfiguration.java
@@ -20,8 +20,11 @@
import javax.annotation.PostConstruct;
import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.BeanFactoryUtils;
+import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.config.AbstractFactoryBean;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
@@ -131,8 +134,19 @@ public FrameworkEndpointHandlerMapping oauth2EndpointHandlerMapping() throws Exc
}
@Bean
- public ConsumerTokenServices consumerTokenServices() throws Exception {
- return getEndpointsConfigurer().getConsumerTokenServices();
+ public FactoryBean consumerTokenServices() throws Exception {
+ return new AbstractFactoryBean() {
+
+ @Override
+ public Class> getObjectType() {
+ return ConsumerTokenServices.class;
+ }
+
+ @Override
+ protected ConsumerTokenServices createInstance() throws Exception {
+ return getEndpointsConfigurer().getConsumerTokenServices();
+ }
+ };
}
/**
@@ -146,13 +160,18 @@ public ConsumerTokenServices consumerTokenServices() throws Exception {
* @return an AuthorizationServerTokenServices
*/
@Bean
- public AuthorizationServerTokenServices defaultAuthorizationServerTokenServices() {
- return endpoints.getDefaultAuthorizationServerTokenServices();
+ public FactoryBean defaultAuthorizationServerTokenServices() {
+ return new AuthorizationServerTokenServicesFactoryBean(endpoints);
}
public AuthorizationServerEndpointsConfigurer getEndpointsConfigurer() {
if (!endpoints.isTokenServicesOverride()) {
- endpoints.tokenServices(defaultAuthorizationServerTokenServices());
+ try {
+ endpoints.tokenServices(endpoints.getDefaultAuthorizationServerTokenServices());
+ }
+ catch (Exception e) {
+ throw new BeanCreationException("Cannot create token services", e);
+ }
}
return endpoints;
}
@@ -193,6 +212,30 @@ private String extractPath(FrameworkEndpointHandlerMapping mapping, String page)
return "forward:" + path;
}
+ protected static class AuthorizationServerTokenServicesFactoryBean
+ extends AbstractFactoryBean {
+
+ private AuthorizationServerEndpointsConfigurer endpoints;
+
+ protected AuthorizationServerTokenServicesFactoryBean() {
+ }
+
+ public AuthorizationServerTokenServicesFactoryBean(
+ AuthorizationServerEndpointsConfigurer endpoints) {
+ this.endpoints = endpoints;
+ }
+
+ @Override
+ public Class> getObjectType() {
+ return AuthorizationServerTokenServices.class;
+ }
+
+ @Override
+ protected AuthorizationServerTokenServices createInstance() throws Exception {
+ return endpoints.getDefaultAuthorizationServerTokenServices();
+ }
+ }
+
@Component
protected static class TokenKeyEndpointRegistrar implements BeanDefinitionRegistryPostProcessor {
diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerEndpointsConfigurer.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerEndpointsConfigurer.java
index dc780e878..0529e0849 100644
--- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerEndpointsConfigurer.java
+++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerEndpointsConfigurer.java
@@ -15,15 +15,6 @@
*/
package org.springframework.security.oauth2.config.annotation.web.configurers;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.http.HttpMethod;
@@ -36,17 +27,8 @@
import org.springframework.security.oauth2.common.util.ProxyCreator;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
-import org.springframework.security.oauth2.provider.ClientDetailsService;
-import org.springframework.security.oauth2.provider.CompositeTokenGranter;
-import org.springframework.security.oauth2.provider.OAuth2RequestFactory;
-import org.springframework.security.oauth2.provider.OAuth2RequestValidator;
-import org.springframework.security.oauth2.provider.TokenGranter;
-import org.springframework.security.oauth2.provider.TokenRequest;
-import org.springframework.security.oauth2.provider.approval.ApprovalStore;
-import org.springframework.security.oauth2.provider.approval.ApprovalStoreUserApprovalHandler;
-import org.springframework.security.oauth2.provider.approval.TokenApprovalStore;
-import org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler;
-import org.springframework.security.oauth2.provider.approval.UserApprovalHandler;
+import org.springframework.security.oauth2.provider.*;
+import org.springframework.security.oauth2.provider.approval.*;
import org.springframework.security.oauth2.provider.client.ClientCredentialsTokenGranter;
import org.springframework.security.oauth2.provider.client.InMemoryClientDetailsService;
import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices;
@@ -55,19 +37,13 @@
import org.springframework.security.oauth2.provider.endpoint.FrameworkEndpointHandlerMapping;
import org.springframework.security.oauth2.provider.error.DefaultWebResponseExceptionTranslator;
import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator;
+import org.springframework.security.oauth2.provider.exchange.TokenExchangeTokenGranter;
import org.springframework.security.oauth2.provider.implicit.ImplicitTokenGranter;
import org.springframework.security.oauth2.provider.password.ResourceOwnerPasswordTokenGranter;
import org.springframework.security.oauth2.provider.refresh.RefreshTokenGranter;
import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory;
import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestValidator;
-import org.springframework.security.oauth2.provider.token.AccessTokenConverter;
-import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
-import org.springframework.security.oauth2.provider.token.ConsumerTokenServices;
-import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter;
-import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
-import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;
-import org.springframework.security.oauth2.provider.token.TokenEnhancer;
-import org.springframework.security.oauth2.provider.token.TokenStore;
+import org.springframework.security.oauth2.provider.token.*;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
@@ -76,9 +52,11 @@
import org.springframework.web.context.request.WebRequestInterceptor;
import org.springframework.web.servlet.HandlerInterceptor;
+import java.util.*;
+
/**
* Configure the properties and enhanced functionality of the Authorization Server endpoints.
- *
+ *
* @author Rob Winch
* @author Dave Syer
* @since 2.0
@@ -242,7 +220,7 @@ public AuthorizationServerEndpointsConfigurer approvalStore(ApprovalStore approv
* Explicitly disable the approval store, even if one would normally be added automatically (usually when JWT is not
* used). Without an approval store the user can only be asked to approve or deny a grant without any more granular
* decisions.
- *
+ *
* @return this for fluent builder
*/
public AuthorizationServerEndpointsConfigurer approvalStoreDisabled() {
@@ -277,7 +255,7 @@ public AuthorizationServerEndpointsConfigurer exceptionTranslator(WebResponseExc
/**
* The AuthenticationManager for the password grant.
- *
+ *
* @param authenticationManager an AuthenticationManager, fully initialized
* @return this for a fluent style
*/
@@ -544,8 +522,9 @@ private List getDefaultTokenGranters() {
if (authenticationManager != null) {
tokenGranters.add(new ResourceOwnerPasswordTokenGranter(authenticationManager, tokenServices,
clientDetails, requestFactory));
+ tokenGranters.add(new TokenExchangeTokenGranter(authenticationManager, tokenServices, clientDetails, requestFactory));
}
- return tokenGranters;
+ return tokenGranters;
}
private TokenGranter tokenGranter() {
diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/AuthorizationServerBeanDefinitionParser.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/AuthorizationServerBeanDefinitionParser.java
index 391d74a8c..b0f6216aa 100644
--- a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/AuthorizationServerBeanDefinitionParser.java
+++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/xml/AuthorizationServerBeanDefinitionParser.java
@@ -28,6 +28,7 @@
import org.springframework.security.oauth2.provider.code.AuthorizationCodeTokenGranter;
import org.springframework.security.oauth2.provider.code.InMemoryAuthorizationCodeServices;
import org.springframework.security.oauth2.provider.endpoint.*;
+import org.springframework.security.oauth2.provider.exchange.TokenExchangeTokenGranter;
import org.springframework.security.oauth2.provider.implicit.ImplicitTokenGranter;
import org.springframework.security.oauth2.provider.password.ResourceOwnerPasswordTokenGranter;
import org.springframework.security.oauth2.provider.refresh.RefreshTokenGranter;
@@ -209,13 +210,13 @@ protected AbstractBeanDefinition parseEndpointAndReturnFilter(Element element,
"password");
if (clientPasswordElement != null && !"true"
.equalsIgnoreCase(clientPasswordElement.getAttribute("disabled"))) {
- BeanDefinitionBuilder clientPasswordTokenGranter = BeanDefinitionBuilder
- .rootBeanDefinition(ResourceOwnerPasswordTokenGranter.class);
String authenticationManagerRef = clientPasswordElement
.getAttribute("authentication-manager-ref");
if (!StringUtils.hasText(authenticationManagerRef)) {
authenticationManagerRef = BeanIds.AUTHENTICATION_MANAGER;
}
+ BeanDefinitionBuilder clientPasswordTokenGranter = BeanDefinitionBuilder
+ .rootBeanDefinition(ResourceOwnerPasswordTokenGranter.class);
clientPasswordTokenGranter
.addConstructorArgReference(authenticationManagerRef);
clientPasswordTokenGranter.addConstructorArgReference(tokenServicesRef);
@@ -223,6 +224,15 @@ protected AbstractBeanDefinition parseEndpointAndReturnFilter(Element element,
clientPasswordTokenGranter
.addConstructorArgReference(oAuth2RequestFactoryRef);
tokenGranters.add(clientPasswordTokenGranter.getBeanDefinition());
+ BeanDefinitionBuilder tokenExchangeTokenGranter = BeanDefinitionBuilder
+ .rootBeanDefinition(TokenExchangeTokenGranter.class);
+ tokenExchangeTokenGranter
+ .addConstructorArgReference(authenticationManagerRef);
+ tokenExchangeTokenGranter.addConstructorArgReference(tokenServicesRef);
+ tokenExchangeTokenGranter.addConstructorArgReference(clientDetailsRef);
+ tokenExchangeTokenGranter
+ .addConstructorArgReference(oAuth2RequestFactoryRef);
+ tokenGranters.add(tokenExchangeTokenGranter.getBeanDefinition());
}
List customGrantElements = DomUtils
.getChildElementsByTagName(element, "custom-grant");
diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/exchange/DefaultTokenExchangeAuthenticationProvider.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/exchange/DefaultTokenExchangeAuthenticationProvider.java
new file mode 100644
index 000000000..37ba8cfd1
--- /dev/null
+++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/exchange/DefaultTokenExchangeAuthenticationProvider.java
@@ -0,0 +1,46 @@
+package org.springframework.security.oauth2.provider.exchange;
+
+import org.springframework.security.authentication.AuthenticationProvider;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
+import org.springframework.security.core.authority.mapping.NullAuthoritiesMapper;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.util.Assert;
+
+/**
+ * {@link AuthenticationProvider} that supports {@link TokenExchangeAuthenticationToken}.
+ *
+ * @author Ryan Murfitt
+ */
+public class DefaultTokenExchangeAuthenticationProvider implements AuthenticationProvider {
+
+ private TokenExchangeService tokenExchangeService;
+ private GrantedAuthoritiesMapper authoritiesMapper = new NullAuthoritiesMapper();
+
+ @Override
+ public Authentication authenticate(Authentication authentication) throws AuthenticationException {
+ Assert.isInstanceOf(TokenExchangeAuthenticationToken.class, authentication, "Only TokenExchangeAuthenticationToken is supported");
+ UserDetails user = this.tokenExchangeService.loadUserDetailsFromToken((TokenExchangeAuthenticationToken) authentication);
+ return createSuccessAuthentication(user, (TokenExchangeAuthenticationToken) authentication);
+ }
+
+ private Authentication createSuccessAuthentication(UserDetails user, TokenExchangeAuthenticationToken token) {
+ TokenExchangeAuthenticationToken result = new TokenExchangeAuthenticationToken(user, token.getPrincipal(), token.getClientDetails(), this.authoritiesMapper.mapAuthorities(user.getAuthorities()));
+ result.setDetails(token.getDetails());
+ return result;
+ }
+
+ @Override
+ public boolean supports(Class> authentication) {
+ return TokenExchangeAuthenticationToken.class.isAssignableFrom(authentication);
+ }
+
+ public void setTokenExchangeService(TokenExchangeService tokenExchangeService) {
+ this.tokenExchangeService = tokenExchangeService;
+ }
+
+ public void setAuthoritiesMapper(GrantedAuthoritiesMapper authoritiesMapper) {
+ this.authoritiesMapper = authoritiesMapper;
+ }
+}
diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/exchange/TokenExchangeAuthenticationToken.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/exchange/TokenExchangeAuthenticationToken.java
new file mode 100644
index 000000000..300fe0631
--- /dev/null
+++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/exchange/TokenExchangeAuthenticationToken.java
@@ -0,0 +1,53 @@
+package org.springframework.security.oauth2.provider.exchange;
+
+import org.springframework.security.authentication.AbstractAuthenticationToken;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.oauth2.provider.ClientDetails;
+
+import java.util.Collection;
+
+/**
+ * Token that represents a token-exchange authentication request.
+ *
+ * Similar to {@link org.springframework.security.authentication.UsernamePasswordAuthenticationToken} where the principal
+ * represents the 'subject_token', but once authenticated, the principal represents the user, and the credentials represents
+ * the 'subject_token'.
+ *
+ * @author Ryan Murfitt
+ */
+public class TokenExchangeAuthenticationToken extends AbstractAuthenticationToken {
+
+ private final Object principal;
+ private final ClientDetails clientDetails;
+ private final Object credentials;
+
+ TokenExchangeAuthenticationToken(Object principal, ClientDetails clientDetails) {
+ super(null);
+ this.principal = principal;
+ this.credentials = null;
+ this.clientDetails = clientDetails;
+ this.setAuthenticated(false);
+ }
+
+ TokenExchangeAuthenticationToken(Object principal, Object credentials, ClientDetails clientDetails, Collection extends GrantedAuthority> authorities) {
+ super(authorities);
+ this.principal = principal;
+ this.credentials = credentials;
+ this.clientDetails = clientDetails;
+ this.setAuthenticated(true);
+ }
+
+ @Override
+ public Object getCredentials() {
+ return credentials;
+ }
+
+ @Override
+ public Object getPrincipal() {
+ return principal;
+ }
+
+ public ClientDetails getClientDetails() {
+ return clientDetails;
+ }
+}
diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/exchange/TokenExchangeService.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/exchange/TokenExchangeService.java
new file mode 100644
index 000000000..16dda8707
--- /dev/null
+++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/exchange/TokenExchangeService.java
@@ -0,0 +1,16 @@
+package org.springframework.security.oauth2.provider.exchange;
+
+import org.springframework.security.authentication.AccountStatusException;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
+
+/**
+ * {@link TokenExchangeService} deals with validating the supplied {@link TokenExchangeAuthenticationToken} which details the
+ * token-exchange request, and returning the user associated with it.
+ *
+ * @author Ryan Murfitt
+ */
+public interface TokenExchangeService {
+
+ UserDetails loadUserDetailsFromToken(TokenExchangeAuthenticationToken tokenAuth) throws AccountStatusException, InvalidTokenException;
+}
diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/exchange/TokenExchangeTokenGranter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/exchange/TokenExchangeTokenGranter.java
new file mode 100644
index 000000000..66e951391
--- /dev/null
+++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/exchange/TokenExchangeTokenGranter.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2002-2011 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.security.oauth2.provider.exchange;
+
+import org.springframework.security.authentication.AccountStatusException;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.oauth2.common.exceptions.InvalidGrantException;
+import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
+import org.springframework.security.oauth2.provider.*;
+import org.springframework.security.oauth2.provider.token.AbstractTokenGranter;
+import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * Supports the proposed token-exchange grant flow from draft-ietf-oauth-token-exchange
+ *
+ * @author Ryan Murfitt
+ */
+public class TokenExchangeTokenGranter extends AbstractTokenGranter {
+
+ private static final String GRANT_TYPE = "token-exchange";
+ private static final String SUBJECT_TOKEN_CLAIM = "subject_token";
+
+ private final AuthenticationManager authenticationManager;
+
+ public TokenExchangeTokenGranter(AuthenticationManager authenticationManager,
+ AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory) {
+ this(authenticationManager, tokenServices, clientDetailsService, requestFactory, GRANT_TYPE);
+ }
+
+ protected TokenExchangeTokenGranter(AuthenticationManager authenticationManager, AuthorizationServerTokenServices tokenServices,
+ ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory, String grantType) {
+ super(tokenServices, clientDetailsService, requestFactory, grantType);
+ this.authenticationManager = authenticationManager;
+ }
+
+ @Override
+ protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) {
+
+ Map parameters = new LinkedHashMap(tokenRequest.getRequestParameters());
+ String subjectToken = parameters.get(SUBJECT_TOKEN_CLAIM);
+
+ TokenExchangeAuthenticationToken tokenAuth = new TokenExchangeAuthenticationToken(subjectToken, client);
+ tokenAuth.setDetails(parameters);
+ Authentication userAuth;
+ try {
+ userAuth = authenticationManager.authenticate(tokenAuth);
+ } catch (AccountStatusException ase) {
+ //covers expired, locked, disabled cases (mentioned in section 5.2, draft 31)
+ throw new InvalidGrantException(ase.getMessage());
+ } catch (InvalidTokenException e) {
+ // If the supplied subject token is invalid
+ throw new InvalidGrantException(e.getMessage());
+ }
+ if (userAuth == null || !userAuth.isAuthenticated()) {
+ throw new InvalidGrantException("Could not authenticate user");
+ }
+
+ OAuth2Request storedOAuth2Request = getRequestFactory().createOAuth2Request(client, tokenRequest);
+ return new OAuth2Authentication(storedOAuth2Request, userAuth);
+ }
+}
diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkAttributes.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkAttributes.java
new file mode 100644
index 000000000..642dcc430
--- /dev/null
+++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkAttributes.java
@@ -0,0 +1,62 @@
+/*
+ * 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.security.oauth2.provider.token.store.jwk;
+
+/**
+ * Shared attribute values used by {@link JwkTokenStore} and associated collaborators.
+ *
+ * @author Joe Grandja
+ */
+final class JwkAttributes {
+
+ /**
+ * The "kid" (key ID) parameter used in a JWT header and in a JWK.
+ */
+ static final String KEY_ID = "kid";
+
+ /**
+ * The "kty" (key type) parameter identifies the cryptographic algorithm family
+ * used by a JWK, for example, "RSA" or "EC".
+ */
+ static final String KEY_TYPE = "kty";
+
+ /**
+ * The "alg" (algorithm) parameter used in a JWT header and in a JWK.
+ */
+ static final String ALGORITHM = "alg";
+
+ /**
+ * The "use" (public key use) parameter identifies the intended use of the public key.
+ * For example, whether a public key is used for encrypting data or verifying the signature on data.
+ */
+ static final String PUBLIC_KEY_USE = "use";
+
+ /**
+ * The "n" (modulus) parameter contains the modulus value for a RSA public key.
+ */
+ static final String RSA_PUBLIC_KEY_MODULUS = "n";
+
+ /**
+ * The "e" (exponent) parameter contains the exponent value for a RSA public key.
+ */
+ static final String RSA_PUBLIC_KEY_EXPONENT = "e";
+
+ /**
+ * A JWK Set is a JSON object that has a "keys" member
+ * and its value is an array (set) of JWKs.
+ */
+ static final String KEYS = "keys";
+}
\ No newline at end of file
diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkDefinition.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkDefinition.java
new file mode 100644
index 000000000..2768ca3f1
--- /dev/null
+++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkDefinition.java
@@ -0,0 +1,196 @@
+/*
+ * 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.security.oauth2.provider.token.store.jwk;
+
+/**
+ * The base representation of a JSON Web Key (JWK).
+ *
+ * @see JSON Web Key (JWK)
+ *
+ * @author Joe Grandja
+ */
+abstract class JwkDefinition {
+ private final String keyId;
+ private final KeyType keyType;
+ private final PublicKeyUse publicKeyUse;
+ private final CryptoAlgorithm algorithm;
+
+ /**
+ * Creates an instance with the common attributes of a JWK.
+ *
+ * @param keyId the Key ID
+ * @param keyType the Key Type
+ * @param publicKeyUse the intended use of the Public Key
+ * @param algorithm the algorithm intended to be used
+ */
+ protected JwkDefinition(String keyId,
+ KeyType keyType,
+ PublicKeyUse publicKeyUse,
+ CryptoAlgorithm algorithm) {
+ this.keyId = keyId;
+ this.keyType = keyType;
+ this.publicKeyUse = publicKeyUse;
+ this.algorithm = algorithm;
+ }
+
+ /**
+ * @return the Key ID ("kid")
+ */
+ String getKeyId() {
+ return this.keyId;
+ }
+
+ /**
+ * @return the Key Type ("kty")
+ */
+ KeyType getKeyType() {
+ return this.keyType;
+ }
+
+ /**
+ * @return the intended use of the Public Key ("use")
+ */
+ PublicKeyUse getPublicKeyUse() {
+ return this.publicKeyUse;
+ }
+
+ /**
+ *
+ * @return the algorithm intended to be used ("alg")
+ */
+ CryptoAlgorithm getAlgorithm() {
+ return this.algorithm;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || this.getClass() != obj.getClass()) {
+ return false;
+ }
+
+ JwkDefinition that = (JwkDefinition) obj;
+ if (!this.getKeyId().equals(that.getKeyId())) {
+ return false;
+ }
+
+ return this.getKeyType().equals(that.getKeyType());
+ }
+
+ @Override
+ public int hashCode() {
+ int result = this.getKeyId().hashCode();
+ result = 31 * result + this.getKeyType().hashCode();
+ return result;
+ }
+
+ /**
+ * The defined Key Type ("kty") values.
+ */
+ enum KeyType {
+ RSA("RSA"),
+ EC("EC"),
+ OCT("oct");
+
+ private final String value;
+
+ KeyType(String value) {
+ this.value = value;
+ }
+
+ String value() {
+ return this.value;
+ }
+
+ static KeyType fromValue(String value) {
+ KeyType result = null;
+ for (KeyType keyType : values()) {
+ if (keyType.value().equals(value)) {
+ result = keyType;
+ break;
+ }
+ }
+ return result;
+ }
+ }
+
+ /**
+ * The defined Public Key Use ("use") values.
+ */
+ enum PublicKeyUse {
+ SIG("sig"),
+ ENC("enc");
+
+ private final String value;
+
+ PublicKeyUse(String value) {
+ this.value = value;
+ }
+
+ String value() {
+ return this.value;
+ }
+
+ static PublicKeyUse fromValue(String value) {
+ PublicKeyUse result = null;
+ for (PublicKeyUse publicKeyUse : values()) {
+ if (publicKeyUse.value().equals(value)) {
+ result = publicKeyUse;
+ break;
+ }
+ }
+ return result;
+ }
+ }
+
+ /**
+ * The defined Algorithm ("alg") values.
+ */
+ enum CryptoAlgorithm {
+ RS256("SHA256withRSA", "RS256"),
+ RS384("SHA384withRSA", "RS384"),
+ RS512("SHA512withRSA", "RS512");
+
+ private final String standardName; // JCA Standard Name
+ private final String headerParamValue;
+
+ CryptoAlgorithm(String standardName, String headerParamValue) {
+ this.standardName = standardName;
+ this.headerParamValue = headerParamValue;
+ }
+
+ String standardName() {
+ return this.standardName;
+ }
+
+ String headerParamValue() {
+ return this.headerParamValue;
+ }
+
+ static CryptoAlgorithm fromHeaderParamValue(String headerParamValue) {
+ CryptoAlgorithm result = null;
+ for (CryptoAlgorithm algorithm : values()) {
+ if (algorithm.headerParamValue().equals(headerParamValue)) {
+ result = algorithm;
+ break;
+ }
+ }
+ return result;
+ }
+ }
+}
\ No newline at end of file
diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkDefinitionSource.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkDefinitionSource.java
new file mode 100644
index 000000000..de643ff03
--- /dev/null
+++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkDefinitionSource.java
@@ -0,0 +1,180 @@
+/*
+ * 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.security.oauth2.provider.token.store.jwk;
+
+import org.springframework.security.jwt.codec.Codecs;
+import org.springframework.security.jwt.crypto.sign.RsaVerifier;
+import org.springframework.security.jwt.crypto.sign.SignatureVerifier;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigInteger;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.security.KeyFactory;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.RSAPublicKeySpec;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * A source for JSON Web Key(s) (JWK) that is solely responsible for fetching (and caching)
+ * the JWK Set (a set of JWKs) from the URL supplied to the constructor.
+ *
+ * @see JwkSetConverter
+ * @see JwkDefinition
+ * @see SignatureVerifier
+ * @see JWK Set Format
+ *
+ * @author Joe Grandja
+ */
+class JwkDefinitionSource {
+ private final URL jwkSetUrl;
+ private final Map jwkDefinitions = new ConcurrentHashMap();
+ private static final JwkSetConverter jwkSetConverter = new JwkSetConverter();
+
+ /**
+ * Creates a new instance using the provided URL as the location for the JWK Set.
+ *
+ * @param jwkSetUrl the JWK Set URL
+ */
+ JwkDefinitionSource(String jwkSetUrl) {
+ try {
+ this.jwkSetUrl = new URL(jwkSetUrl);
+ } catch (MalformedURLException ex) {
+ throw new IllegalArgumentException("Invalid JWK Set URL: " + ex.getMessage(), ex);
+ }
+ }
+
+ /**
+ * Returns the JWK definition matching the provided keyId ("kid").
+ *
+ * @param keyId the Key ID ("kid")
+ * @return the matching {@link JwkDefinition} or null if not found
+ */
+ JwkDefinition getDefinition(String keyId) {
+ JwkDefinition result = null;
+ JwkDefinitionHolder jwkDefinitionHolder = this.jwkDefinitions.get(keyId);
+ if (jwkDefinitionHolder != null) {
+ result = jwkDefinitionHolder.getJwkDefinition();
+ }
+ return result;
+ }
+
+ /**
+ * Returns the JWK definition matching the provided keyId ("kid").
+ * If the JWK definition is not available in the internal cache then {@link #loadJwkDefinitions(URL)}
+ * will be called (to re-load the cache) and then followed-up with a second attempt to locate the JWK definition.
+ *
+ * @param keyId the Key ID ("kid")
+ * @return the matching {@link JwkDefinition} or null if not found
+ */
+ JwkDefinition getDefinitionLoadIfNecessary(String keyId) {
+ JwkDefinition result = this.getDefinition(keyId);
+ if (result != null) {
+ return result;
+ }
+ this.jwkDefinitions.clear();
+ this.jwkDefinitions.putAll(loadJwkDefinitions(this.jwkSetUrl));
+ return this.getDefinition(keyId);
+ }
+
+ /**
+ * Returns the {@link SignatureVerifier} matching the provided keyId ("kid").
+ *
+ * @param keyId the Key ID ("kid")
+ * @return the matching {@link SignatureVerifier} or null if not found
+ */
+ SignatureVerifier getVerifier(String keyId) {
+ SignatureVerifier result = null;
+ JwkDefinition jwkDefinition = this.getDefinitionLoadIfNecessary(keyId);
+ if (jwkDefinition != null) {
+ result = this.jwkDefinitions.get(keyId).getSignatureVerifier();
+ }
+ return result;
+ }
+
+ /**
+ * Fetches the JWK Set from the provided URL and
+ * returns a Map keyed by the JWK keyId ("kid")
+ * and mapped to an association of the {@link JwkDefinition} and {@link SignatureVerifier}.
+ * Uses a {@link JwkSetConverter} to convert the JWK Set URL source to a set of {@link JwkDefinition}(s)
+ * followed by the instantiation of a {@link SignatureVerifier} which is associated to it's {@link JwkDefinition}.
+ *
+ * @param jwkSetUrl the JWK Set URL
+ * @return a Map keyed by the JWK keyId and mapped to an association of {@link JwkDefinition} and {@link SignatureVerifier}
+ * @see JwkSetConverter
+ */
+ static Map loadJwkDefinitions(URL jwkSetUrl) {
+ InputStream jwkSetSource;
+ try {
+ jwkSetSource = jwkSetUrl.openStream();
+ } catch (IOException ex) {
+ throw new JwkException("An I/O error occurred while reading from the JWK Set source: " + ex.getMessage(), ex);
+ }
+
+ Set jwkDefinitionSet = jwkSetConverter.convert(jwkSetSource);
+
+ Map jwkDefinitions = new LinkedHashMap();
+
+ for (JwkDefinition jwkDefinition : jwkDefinitionSet) {
+ if (JwkDefinition.KeyType.RSA.equals(jwkDefinition.getKeyType())) {
+ jwkDefinitions.put(jwkDefinition.getKeyId(),
+ new JwkDefinitionHolder(jwkDefinition, createRsaVerifier((RsaJwkDefinition) jwkDefinition)));
+ }
+ }
+
+ return jwkDefinitions;
+ }
+
+ private static RsaVerifier createRsaVerifier(RsaJwkDefinition rsaDefinition) {
+ RsaVerifier result;
+ try {
+ BigInteger modulus = new BigInteger(Codecs.b64UrlDecode(rsaDefinition.getModulus()));
+ BigInteger exponent = new BigInteger(Codecs.b64UrlDecode(rsaDefinition.getExponent()));
+
+ RSAPublicKey rsaPublicKey = (RSAPublicKey) KeyFactory.getInstance("RSA")
+ .generatePublic(new RSAPublicKeySpec(modulus, exponent));
+
+ result = new RsaVerifier(rsaPublicKey, rsaDefinition.getAlgorithm().standardName());
+
+ } catch (Exception ex) {
+ throw new JwkException("An error occurred while creating a RSA Public Key Verifier for " +
+ rsaDefinition.getKeyId() + " : " + ex.getMessage(), ex);
+ }
+ return result;
+ }
+
+ static class JwkDefinitionHolder {
+ private final JwkDefinition jwkDefinition;
+ private final SignatureVerifier signatureVerifier;
+
+ private JwkDefinitionHolder(JwkDefinition jwkDefinition, SignatureVerifier signatureVerifier) {
+ this.jwkDefinition = jwkDefinition;
+ this.signatureVerifier = signatureVerifier;
+ }
+
+ private JwkDefinition getJwkDefinition() {
+ return jwkDefinition;
+ }
+
+ private SignatureVerifier getSignatureVerifier() {
+ return signatureVerifier;
+ }
+ }
+}
\ No newline at end of file
diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkException.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkException.java
new file mode 100644
index 000000000..1d3211dfb
--- /dev/null
+++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkException.java
@@ -0,0 +1,59 @@
+/*
+ * 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.security.oauth2.provider.token.store.jwk;
+
+import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
+
+/**
+ * General exception for JSON Web Key (JWK) related errors.
+ *
+ * @author Joe Grandja
+ */
+public class JwkException extends OAuth2Exception {
+ private static final String SERVER_ERROR_ERROR_CODE = "server_error";
+ private String errorCode = SERVER_ERROR_ERROR_CODE;
+ private int httpStatus = 500;
+
+ public JwkException(String message) {
+ super(message);
+ }
+
+ public JwkException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * Returns the error used in the OAuth2 Error Response
+ * sent back to the caller. The default is "server_error".
+ *
+ * @return the error used in the OAuth2 Error Response
+ */
+ @Override
+ public String getOAuth2ErrorCode() {
+ return this.errorCode;
+ }
+
+ /**
+ * Returns the Http Status used in the OAuth2 Error Response
+ * sent back to the caller. The default is 500.
+ *
+ * @return the Http Status set on the OAuth2 Error Response
+ */
+ @Override
+ public int getHttpErrorCode() {
+ return this.httpStatus;
+ }
+}
\ No newline at end of file
diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkSetConverter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkSetConverter.java
new file mode 100644
index 000000000..e0284261c
--- /dev/null
+++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkSetConverter.java
@@ -0,0 +1,178 @@
+/*
+ * 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.security.oauth2.provider.token.store.jwk;
+
+import com.fasterxml.jackson.core.JsonFactory;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonToken;
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.util.StringUtils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+
+import static org.springframework.security.oauth2.provider.token.store.jwk.JwkAttributes.*;
+
+/**
+ * A {@link Converter} that converts the supplied InputStream to a Set of {@link JwkDefinition}(s).
+ * The source of the InputStream must be a JWK Set representation which is a JSON object
+ * that has a "keys" member and its value is an array of JWKs.
+ *
+ *
+ *
+ * NOTE: The Key Type ("kty") currently supported by this {@link Converter} is {@link JwkDefinition.KeyType#RSA}.
+ *
+ *
+ *
+ * @see JwkDefinition
+ * @see JWK Set Format
+ *
+ * @author Joe Grandja
+ */
+class JwkSetConverter implements Converter> {
+ private final JsonFactory factory = new JsonFactory();
+
+ /**
+ * Converts the supplied InputStream to a Set of {@link JwkDefinition}(s).
+ *
+ * @param jwkSetSource the source for the JWK Set
+ * @return a Set of {@link JwkDefinition}(s)
+ * @throws JwkException if the JWK Set JSON object is invalid
+ */
+ @Override
+ public Set convert(InputStream jwkSetSource) {
+ Set jwkDefinitions;
+ JsonParser parser = null;
+
+ try {
+ parser = this.factory.createParser(jwkSetSource);
+
+ if (parser.nextToken() != JsonToken.START_OBJECT) {
+ throw new JwkException("Invalid JWK Set Object.");
+ }
+ if (parser.nextToken() != JsonToken.FIELD_NAME) {
+ throw new JwkException("Invalid JWK Set Object.");
+ }
+ if (!parser.getCurrentName().equals(KEYS)) {
+ throw new JwkException("Invalid JWK Set Object. The JWK Set MUST have a " + KEYS + " attribute.");
+ }
+ if (parser.nextToken() != JsonToken.START_ARRAY) {
+ throw new JwkException("Invalid JWK Set Object. The JWK Set MUST have an array of JWK(s).");
+ }
+
+ jwkDefinitions = new LinkedHashSet();
+ Map attributes = new HashMap();
+
+ while (parser.nextToken() == JsonToken.START_OBJECT) {
+ while (parser.nextToken() == JsonToken.FIELD_NAME) {
+ String attributeName = parser.getCurrentName();
+ parser.nextToken();
+ String attributeValue = parser.getValueAsString();
+ attributes.put(attributeName, attributeValue);
+ }
+ JwkDefinition jwkDefinition = this.createJwkDefinition(attributes);
+ if (!jwkDefinitions.add(jwkDefinition)) {
+ throw new JwkException("Duplicate JWK found in Set: " +
+ jwkDefinition.getKeyId() + " (" + KEY_ID + ")");
+ }
+ attributes.clear();
+ }
+
+ } catch (IOException ex) {
+ throw new JwkException("An I/O error occurred while reading the JWK Set: " + ex.getMessage(), ex);
+ } finally {
+ try {
+ if (parser != null) parser.close();
+ } catch (IOException ex) { }
+ }
+
+ return jwkDefinitions;
+ }
+
+ /**
+ * Creates a {@link JwkDefinition} based on the supplied attributes.
+ *
+ * @param attributes the attributes used to create the {@link JwkDefinition}
+ * @return a {@link JwkDefinition}
+ * @throws JwkException if the Key Type ("kty") attribute value is not {@link JwkDefinition.KeyType#RSA}
+ */
+ private JwkDefinition createJwkDefinition(Map attributes) {
+ JwkDefinition.KeyType keyType =
+ JwkDefinition.KeyType.fromValue(attributes.get(KEY_TYPE));
+
+ if (!JwkDefinition.KeyType.RSA.equals(keyType)) {
+ throw new JwkException((keyType != null ? keyType.value() : "unknown") +
+ " (" + KEY_TYPE + ") is currently not supported." +
+ " Valid values for '" + KEY_TYPE + "' are: " + JwkDefinition.KeyType.RSA.value());
+ }
+
+ return this.createRsaJwkDefinition(attributes);
+ }
+
+ /**
+ * Creates a {@link RsaJwkDefinition} based on the supplied attributes.
+ *
+ * @param attributes the attributes used to create the {@link RsaJwkDefinition}
+ * @return a {@link JwkDefinition} representation of a RSA Key
+ * @throws JwkException if at least one attribute value is missing or invalid for a RSA Key
+ */
+ private JwkDefinition createRsaJwkDefinition(Map attributes) {
+ // kid
+ String keyId = attributes.get(KEY_ID);
+ if (!StringUtils.hasText(keyId)) {
+ throw new JwkException(KEY_ID + " is a required attribute for a JWK.");
+ }
+
+ // use
+ JwkDefinition.PublicKeyUse publicKeyUse =
+ JwkDefinition.PublicKeyUse.fromValue(attributes.get(PUBLIC_KEY_USE));
+ if (!JwkDefinition.PublicKeyUse.SIG.equals(publicKeyUse)) {
+ throw new JwkException((publicKeyUse != null ? publicKeyUse.value() : "unknown") +
+ " (" + PUBLIC_KEY_USE + ") is currently not supported.");
+ }
+
+ // alg
+ JwkDefinition.CryptoAlgorithm algorithm =
+ JwkDefinition.CryptoAlgorithm.fromHeaderParamValue(attributes.get(ALGORITHM));
+ if (!JwkDefinition.CryptoAlgorithm.RS256.equals(algorithm) &&
+ !JwkDefinition.CryptoAlgorithm.RS384.equals(algorithm) &&
+ !JwkDefinition.CryptoAlgorithm.RS512.equals(algorithm)) {
+ throw new JwkException((algorithm != null ? algorithm.standardName() : "unknown") +
+ " (" + ALGORITHM + ") is currently not supported.");
+ }
+
+ // n
+ String modulus = attributes.get(RSA_PUBLIC_KEY_MODULUS);
+ if (!StringUtils.hasText(modulus)) {
+ throw new JwkException(RSA_PUBLIC_KEY_MODULUS + " is a required attribute for a RSA JWK.");
+ }
+
+ // e
+ String exponent = attributes.get(RSA_PUBLIC_KEY_EXPONENT);
+ if (!StringUtils.hasText(exponent)) {
+ throw new JwkException(RSA_PUBLIC_KEY_EXPONENT + " is a required attribute for a RSA JWK.");
+ }
+
+ RsaJwkDefinition jwkDefinition = new RsaJwkDefinition(
+ keyId, publicKeyUse, algorithm, modulus, exponent);
+
+ return jwkDefinition;
+ }
+}
\ No newline at end of file
diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkTokenStore.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkTokenStore.java
new file mode 100644
index 000000000..85706ba4a
--- /dev/null
+++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkTokenStore.java
@@ -0,0 +1,250 @@
+/*
+ * 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.security.oauth2.provider.token.store.jwk;
+
+import org.springframework.security.oauth2.common.OAuth2AccessToken;
+import org.springframework.security.oauth2.common.OAuth2RefreshToken;
+import org.springframework.security.oauth2.provider.OAuth2Authentication;
+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.util.Assert;
+
+import java.util.Collection;
+
+/**
+ * A {@link TokenStore} implementation that provides support for verifying the
+ * JSON Web Signature (JWS) for a JSON Web Token (JWT) using a JSON Web Key (JWK).
+ *
+ *
+ *
+ * This {@link TokenStore} implementation is exclusively meant to be used by a Resource Server as
+ * it's sole responsibility is to decode a JWT and verify it's signature (JWS) using the corresponding JWK.
+ *
+ *
+ *
+ * NOTE:
+ * There are a few operations defined by {@link TokenStore} that are not applicable for a Resource Server.
+ * In these cases, the method implementation will explicitly throw a
+ * {@link JwkException} reporting "This operation is not supported".
+ *
+ *
+ *
+ * The unsupported operations are as follows:
+ *
+ * - {@link #storeAccessToken(OAuth2AccessToken, OAuth2Authentication)}
+ * - {@link #removeAccessToken(OAuth2AccessToken)}
+ * - {@link #storeRefreshToken(OAuth2RefreshToken, OAuth2Authentication)}
+ * - {@link #readRefreshToken(String)}
+ * - {@link #readAuthenticationForRefreshToken(OAuth2RefreshToken)}
+ * - {@link #removeRefreshToken(OAuth2RefreshToken)}
+ * - {@link #removeAccessTokenUsingRefreshToken(OAuth2RefreshToken)}
+ * - {@link #getAccessToken(OAuth2Authentication)}
+ * - {@link #findTokensByClientIdAndUserName(String, String)}
+ * - {@link #findTokensByClientId(String)}
+ *
+ *
+ *
+ * This implementation delegates to an internal instance of a {@link JwtTokenStore} which uses a
+ * specialized extension of {@link JwtAccessTokenConverter}.
+ * This specialized {@link JwtAccessTokenConverter} is capable of fetching (and caching)
+ * the JWK Set (a set of JWKs) from the URL supplied to the constructor of this implementation.
+ *
+ *
+ *
+ * The {@link JwtAccessTokenConverter} will verify the JWS in the following step sequence:
+ *
+ *
+ *
+ * - Extract the "kid" parameter from the JWT header.
+ * - Find the matching JWK with the corresponding "kid" attribute.
+ * - Obtain the
SignatureVerifier associated with the JWK and verify the signature.
+ *
+ *
+ * NOTE: The algorithms currently supported by this implementation are: RS256, RS384 and RS512.
+ *
+ *
+ *
+ * @see JwtTokenStore
+ * @see JSON Web Key (JWK)
+ * @see JSON Web Token (JWT)
+ * @see JSON Web Signature (JWS)
+ *
+ * @author Joe Grandja
+ */
+public final class JwkTokenStore implements TokenStore {
+ private final JwtTokenStore delegate;
+
+ /**
+ * Creates a new instance using the provided URL as the location for the JWK Set.
+ *
+ * @param jwkSetUrl the JWK Set URL
+ */
+ public JwkTokenStore(String jwkSetUrl) {
+ Assert.hasText(jwkSetUrl, "jwkSetUrl cannot be empty");
+ JwkDefinitionSource jwkDefinitionSource = new JwkDefinitionSource(jwkSetUrl);
+ JwkVerifyingJwtAccessTokenConverter accessTokenConverter =
+ new JwkVerifyingJwtAccessTokenConverter(jwkDefinitionSource);
+ this.delegate = new JwtTokenStore(accessTokenConverter);
+ }
+
+ /**
+ * Delegates to the internal instance {@link JwtTokenStore#readAuthentication(OAuth2AccessToken)}.
+ *
+ * @param token the access token
+ * @return the {@link OAuth2Authentication} representation of the access token
+ */
+ @Override
+ public OAuth2Authentication readAuthentication(OAuth2AccessToken token) {
+ return this.delegate.readAuthentication(token);
+ }
+
+ /**
+ * Delegates to the internal instance {@link JwtTokenStore#readAuthentication(String)}.
+ *
+ * @param tokenValue the access token value
+ * @return the {@link OAuth2Authentication} representation of the access token
+ */
+ @Override
+ public OAuth2Authentication readAuthentication(String tokenValue) {
+ return this.delegate.readAuthentication(tokenValue);
+ }
+
+ /**
+ * This operation is not applicable for a Resource Server
+ * and if called, will throw a {@link JwkException}.
+ *
+ * @throws JwkException reporting this operation is not supported
+ */
+ @Override
+ public void storeAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) {
+ throw this.operationNotSupported();
+ }
+
+ /**
+ * Delegates to the internal instance {@link JwtTokenStore#readAccessToken(String)}.
+ *
+ * @param tokenValue the access token value
+ * @return the {@link OAuth2AccessToken} representation of the access token value
+ */
+ @Override
+ public OAuth2AccessToken readAccessToken(String tokenValue) {
+ return this.delegate.readAccessToken(tokenValue);
+ }
+
+ /**
+ * This operation is not applicable for a Resource Server
+ * and if called, will throw a {@link JwkException}.
+ *
+ * @throws JwkException reporting this operation is not supported
+ */
+ @Override
+ public void removeAccessToken(OAuth2AccessToken token) {
+ throw this.operationNotSupported();
+ }
+
+ /**
+ * This operation is not applicable for a Resource Server
+ * and if called, will throw a {@link JwkException}.
+ *
+ * @throws JwkException reporting this operation is not supported
+ */
+ @Override
+ public void storeRefreshToken(OAuth2RefreshToken refreshToken, OAuth2Authentication authentication) {
+ throw this.operationNotSupported();
+ }
+
+ /**
+ * This operation is not applicable for a Resource Server
+ * and if called, will throw a {@link JwkException}.
+ *
+ * @throws JwkException reporting this operation is not supported
+ */
+ @Override
+ public OAuth2RefreshToken readRefreshToken(String tokenValue) {
+ throw this.operationNotSupported();
+ }
+
+ /**
+ * This operation is not applicable for a Resource Server
+ * and if called, will throw a {@link JwkException}.
+ *
+ * @throws JwkException reporting this operation is not supported
+ */
+ @Override
+ public OAuth2Authentication readAuthenticationForRefreshToken(OAuth2RefreshToken token) {
+ throw this.operationNotSupported();
+ }
+
+ /**
+ * This operation is not applicable for a Resource Server
+ * and if called, will throw a {@link JwkException}.
+ *
+ * @throws JwkException reporting this operation is not supported
+ */
+ @Override
+ public void removeRefreshToken(OAuth2RefreshToken token) {
+ throw this.operationNotSupported();
+ }
+
+ /**
+ * This operation is not applicable for a Resource Server
+ * and if called, will throw a {@link JwkException}.
+ *
+ * @throws JwkException reporting this operation is not supported
+ */
+ @Override
+ public void removeAccessTokenUsingRefreshToken(OAuth2RefreshToken refreshToken) {
+ throw this.operationNotSupported();
+ }
+
+ /**
+ * This operation is not applicable for a Resource Server
+ * and if called, will throw a {@link JwkException}.
+ *
+ * @throws JwkException reporting this operation is not supported
+ */
+ @Override
+ public OAuth2AccessToken getAccessToken(OAuth2Authentication authentication) {
+ throw this.operationNotSupported();
+ }
+
+ /**
+ * This operation is not applicable for a Resource Server
+ * and if called, will throw a {@link JwkException}.
+ *
+ * @throws JwkException reporting this operation is not supported
+ */
+ @Override
+ public Collection findTokensByClientIdAndUserName(String clientId, String userName) {
+ throw this.operationNotSupported();
+ }
+
+ /**
+ * This operation is not applicable for a Resource Server
+ * and if called, will throw a {@link JwkException}.
+ *
+ * @throws JwkException reporting this operation is not supported
+ */
+ @Override
+ public Collection findTokensByClientId(String clientId) {
+ throw this.operationNotSupported();
+ }
+
+ private JwkException operationNotSupported() {
+ return new JwkException("This operation is not supported.");
+ }
+}
\ No newline at end of file
diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkVerifyingJwtAccessTokenConverter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkVerifyingJwtAccessTokenConverter.java
new file mode 100644
index 000000000..431ade84a
--- /dev/null
+++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkVerifyingJwtAccessTokenConverter.java
@@ -0,0 +1,142 @@
+/*
+ * 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.security.oauth2.provider.token.store.jwk;
+
+import org.springframework.security.jwt.Jwt;
+import org.springframework.security.jwt.JwtHelper;
+import org.springframework.security.jwt.crypto.sign.SignatureVerifier;
+import org.springframework.security.oauth2.common.OAuth2AccessToken;
+import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
+import org.springframework.security.oauth2.common.util.JsonParser;
+import org.springframework.security.oauth2.common.util.JsonParserFactory;
+import org.springframework.security.oauth2.provider.OAuth2Authentication;
+import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
+
+import java.util.Map;
+
+import static org.springframework.security.oauth2.provider.token.store.jwk.JwkAttributes.ALGORITHM;
+import static org.springframework.security.oauth2.provider.token.store.jwk.JwkAttributes.KEY_ID;
+
+/**
+ * A specialized extension of {@link JwtAccessTokenConverter} that is responsible for verifying
+ * the JSON Web Signature (JWS) for a JSON Web Token (JWT) using the corresponding JSON Web Key (JWK).
+ * This implementation is associated with a {@link JwkDefinitionSource} for looking up
+ * the matching {@link JwkDefinition} using the value of the JWT header parameter "kid".
+ *
+ *
+ *
+ * The JWS is verified in the following step sequence:
+ *
+ *
+ *
+ * - Extract the "kid" parameter from the JWT header.
+ * - Find the matching {@link JwkDefinition} from the {@link JwkDefinitionSource} with the corresponding "kid" attribute.
+ * - Obtain the {@link SignatureVerifier} associated with the {@link JwkDefinition} via the {@link JwkDefinitionSource} and verify the signature.
+ *
+ *
+ * NOTE: The algorithms currently supported by this implementation are: RS256, RS384 and RS512.
+ *
+ *
+ *
+ * NOTE: This {@link JwtAccessTokenConverter} does not support signing JWTs (JWS) and therefore
+ * the {@link #encode(OAuth2AccessToken, OAuth2Authentication)} method implementation, if called,
+ * will explicitly throw a {@link JwkException} reporting "JWT signing (JWS) is not supported.".
+ *
+ *
+ *
+ * @see JwtAccessTokenConverter
+ * @see JwtHeaderConverter
+ * @see JwkDefinitionSource
+ * @see JwkDefinition
+ * @see SignatureVerifier
+ * @see JSON Web Key (JWK)
+ * @see JSON Web Token (JWT)
+ * @see JSON Web Signature (JWS)
+ *
+ * @author Joe Grandja
+ */
+class JwkVerifyingJwtAccessTokenConverter extends JwtAccessTokenConverter {
+ private final JwkDefinitionSource jwkDefinitionSource;
+ private final JwtHeaderConverter jwtHeaderConverter = new JwtHeaderConverter();
+ private final JsonParser jsonParser = JsonParserFactory.create();
+
+ /**
+ * Creates a new instance using the provided {@link JwkDefinitionSource}
+ * as the primary source for looking up {@link JwkDefinition}(s).
+ *
+ * @param jwkDefinitionSource the source for {@link JwkDefinition}(s)
+ */
+ JwkVerifyingJwtAccessTokenConverter(JwkDefinitionSource jwkDefinitionSource) {
+ this.jwkDefinitionSource = jwkDefinitionSource;
+ }
+
+ /**
+ * Decodes and validates the supplied JWT followed by signature verification
+ * before returning the Claims from the JWT Payload.
+ *
+ * @param token the JSON Web Token
+ * @return a Map of the JWT Claims
+ * @throws JwkException if the JWT is invalid or if the JWS could not be verified
+ */
+ @Override
+ protected Map decode(String token) {
+ Map headers = this.jwtHeaderConverter.convert(token);
+
+ // Validate "kid" header
+ String keyIdHeader = headers.get(KEY_ID);
+ if (keyIdHeader == null) {
+ throw new InvalidTokenException("Invalid JWT/JWS: " + KEY_ID + " is a required JOSE Header");
+ }
+ JwkDefinition jwkDefinition = this.jwkDefinitionSource.getDefinitionLoadIfNecessary(keyIdHeader);
+ if (jwkDefinition == null) {
+ throw new InvalidTokenException("Invalid JOSE Header " + KEY_ID + " (" + keyIdHeader + ")");
+ }
+
+ // Validate "alg" header
+ String algorithmHeader = headers.get(ALGORITHM);
+ if (algorithmHeader == null) {
+ throw new InvalidTokenException("Invalid JWT/JWS: " + ALGORITHM + " is a required JOSE Header");
+ }
+ if (!algorithmHeader.equals(jwkDefinition.getAlgorithm().headerParamValue())) {
+ throw new InvalidTokenException("Invalid JOSE Header " + ALGORITHM + " (" + algorithmHeader + ")" +
+ " does not match algorithm associated to JWK with " + KEY_ID + " (" + keyIdHeader + ")");
+ }
+
+ // Verify signature
+ SignatureVerifier verifier = this.jwkDefinitionSource.getVerifier(keyIdHeader);
+ Jwt jwt = JwtHelper.decode(token);
+ jwt.verifySignature(verifier);
+
+ Map claims = this.jsonParser.parseMap(jwt.getClaims());
+ if (claims.containsKey(EXP) && claims.get(EXP) instanceof Integer) {
+ Integer expiryInt = (Integer) claims.get(EXP);
+ claims.put(EXP, new Long(expiryInt));
+ }
+
+ return claims;
+ }
+
+ /**
+ * This operation (JWT signing) is not supported and if called,
+ * will throw a {@link JwkException}.
+ *
+ * @throws JwkException
+ */
+ @Override
+ protected String encode(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
+ throw new JwkException("JWT signing (JWS) is not supported.");
+ }
+}
\ No newline at end of file
diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwtHeaderConverter.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwtHeaderConverter.java
new file mode 100644
index 000000000..62981f33b
--- /dev/null
+++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/JwtHeaderConverter.java
@@ -0,0 +1,81 @@
+/*
+ * 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.security.oauth2.provider.token.store.jwk;
+
+import com.fasterxml.jackson.core.JsonFactory;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonToken;
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.security.jwt.codec.Codecs;
+import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A {@link Converter} that converts the supplied String representation of a JWT
+ * to a Map of JWT Header Parameters.
+ *
+ * @see JSON Web Token (JWT)
+ *
+ * @author Joe Grandja
+ */
+class JwtHeaderConverter implements Converter> {
+ private final JsonFactory factory = new JsonFactory();
+
+ /**
+ * Converts the supplied JSON Web Token to a Map of JWT Header Parameters.
+ *
+ * @param token the JSON Web Token
+ * @return a Map of JWT Header Parameters
+ * @throws JwkException if the JWT is invalid
+ */
+ @Override
+ public Map convert(String token) {
+ Map headers;
+
+ int headerEndIndex = token.indexOf('.');
+ if (headerEndIndex == -1) {
+ throw new InvalidTokenException("Invalid JWT. Missing JOSE Header.");
+ }
+ byte[] decodedHeader = Codecs.b64UrlDecode(token.substring(0, headerEndIndex));
+
+ JsonParser parser = null;
+
+ try {
+ parser = this.factory.createParser(decodedHeader);
+ headers = new HashMap();
+ if (parser.nextToken() == JsonToken.START_OBJECT) {
+ while (parser.nextToken() == JsonToken.FIELD_NAME) {
+ String headerName = parser.getCurrentName();
+ parser.nextToken();
+ String headerValue = parser.getValueAsString();
+ headers.put(headerName, headerValue);
+ }
+ }
+
+ } catch (IOException ex) {
+ throw new InvalidTokenException("An I/O error occurred while reading the JWT: " + ex.getMessage(), ex);
+ } finally {
+ try {
+ if (parser != null) parser.close();
+ } catch (IOException ex) { }
+ }
+
+ return headers;
+ }
+}
\ No newline at end of file
diff --git a/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/RsaJwkDefinition.java b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/RsaJwkDefinition.java
new file mode 100644
index 000000000..41655c7af
--- /dev/null
+++ b/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/token/store/jwk/RsaJwkDefinition.java
@@ -0,0 +1,63 @@
+/*
+ * 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.security.oauth2.provider.token.store.jwk;
+
+/**
+ * A JSON Web Key (JWK) representation of a RSA key.
+ *
+ * @see JSON Web Key (JWK)
+ * @see JSON Web Algorithms (JWA)
+ *
+ * @author Joe Grandja
+ */
+final class RsaJwkDefinition extends JwkDefinition {
+ private final String modulus;
+ private final String exponent;
+
+ /**
+ * Creates an instance of a RSA JSON Web Key (JWK).
+ *
+ * @param keyId the Key ID
+ * @param publicKeyUse the intended use of the Public Key
+ * @param algorithm the algorithm intended to be used
+ * @param modulus the modulus value for the Public Key
+ * @param exponent the exponent value for the Public Key
+ */
+ RsaJwkDefinition(String keyId,
+ PublicKeyUse publicKeyUse,
+ CryptoAlgorithm algorithm,
+ String modulus,
+ String exponent) {
+
+ super(keyId, KeyType.RSA, publicKeyUse, algorithm);
+ this.modulus = modulus;
+ this.exponent = exponent;
+ }
+
+ /**
+ * @return the modulus value for the Public Key
+ */
+ String getModulus() {
+ return this.modulus;
+ }
+
+ /**
+ * @return the exponent value for the Public Key
+ */
+ String getExponent() {
+ return this.exponent;
+ }
+}
\ No newline at end of file
diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/TokenServicesMultipleBeansTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/TokenServicesMultipleBeansTests.java
new file mode 100644
index 000000000..d38593d54
--- /dev/null
+++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/config/annotation/TokenServicesMultipleBeansTests.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2015-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.security.oauth2.config.annotation;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.oauth2.config.annotation.TokenServicesMultipleBeansTests.BrokenOAuthApplication;
+import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
+import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
+import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
+import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
+import org.springframework.security.oauth2.provider.token.ConsumerTokenServices;
+import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.web.WebAppConfiguration;
+
+/**
+ * @author Dave Syer
+ *
+ */
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes=BrokenOAuthApplication.class)
+@WebAppConfiguration
+public class TokenServicesMultipleBeansTests {
+
+ @Autowired(required=false)
+ private ResourceServerTokenServices tokenServices;
+
+ @Autowired
+ private AuthorizationServerTokenServices authServerTokenServices;
+
+ @Autowired
+ private ConsumerTokenServices consumerTokenServices;
+
+ @Test
+ public void test() {
+ assertNull(tokenServices);
+ assertNotNull(authServerTokenServices);
+ assertNotNull(consumerTokenServices);
+ }
+
+ @Configuration
+ @EnableAuthorizationServer
+ @EnableResourceServer
+ @EnableWebSecurity
+ protected static class BrokenOAuthApplication extends AuthorizationServerConfigurerAdapter {
+ }
+}
diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/exchange/DefaultTokenExchangeAuthenticationProviderTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/exchange/DefaultTokenExchangeAuthenticationProviderTests.java
new file mode 100644
index 000000000..26f572ead
--- /dev/null
+++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/exchange/DefaultTokenExchangeAuthenticationProviderTests.java
@@ -0,0 +1,75 @@
+package org.springframework.security.oauth2.provider.exchange;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.security.core.userdetails.UserDetails;
+
+import java.util.Collections;
+
+import static org.mockito.Mockito.*;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author Ryan Murfitt
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class DefaultTokenExchangeAuthenticationProviderTests {
+
+ @Mock
+ private TokenExchangeService tokenExchangeService;
+
+ @InjectMocks
+ private DefaultTokenExchangeAuthenticationProvider provider = new DefaultTokenExchangeAuthenticationProvider();
+
+ @Rule
+ public final ExpectedException exception = ExpectedException.none();
+
+ @Test
+ public void authenticateIncorrectTokenType() {
+ UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
+ "rod", "KOala");
+ exception.expect(IllegalArgumentException.class);
+ exception.expectMessage("Only TokenExchangeAuthenticationToken is supported");
+
+ provider.authenticate(token);
+
+ verifyZeroInteractions(this.tokenExchangeService);
+ }
+
+ @Test
+ public void authenticateSuccess() {
+ TokenExchangeAuthenticationToken token = new TokenExchangeAuthenticationToken(
+ "token", null);
+ UserDetails user = new User("bob", "password", Collections.emptyList());
+
+ when(tokenExchangeService.loadUserDetailsFromToken(token)).thenReturn(user);
+
+ Authentication result = provider.authenticate(token);
+
+ assertTrue(result instanceof TokenExchangeAuthenticationToken);
+ assertTrue(result.isAuthenticated());
+ assertSame(result.getPrincipal(), user);
+ assertSame(result.getCredentials(), token.getPrincipal());
+ }
+
+ @Test
+ public void supportsIncorrectTokenType() {
+ assertFalse(provider.supports(UsernamePasswordAuthenticationToken.class));
+ }
+
+ @Test
+ public void supportsSuccess() {
+ assertTrue(provider.supports(TokenExchangeAuthenticationToken.class));
+ }
+
+}
\ No newline at end of file
diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/exchange/TokenExchangeTokenGranterTests.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/exchange/TokenExchangeTokenGranterTests.java
new file mode 100644
index 000000000..3ff11ad04
--- /dev/null
+++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/exchange/TokenExchangeTokenGranterTests.java
@@ -0,0 +1,111 @@
+package org.springframework.security.oauth2.provider.exchange;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.LockedException;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.oauth2.common.OAuth2AccessToken;
+import org.springframework.security.oauth2.common.exceptions.InvalidClientException;
+import org.springframework.security.oauth2.common.exceptions.InvalidGrantException;
+import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
+import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
+import org.springframework.security.oauth2.provider.*;
+import org.springframework.security.oauth2.provider.client.BaseClientDetails;
+import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory;
+import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
+import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.when;
+
+/**
+ * @author Ryan Murfitt
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class TokenExchangeTokenGranterTests {
+
+ private Authentication validUser = new UsernamePasswordAuthenticationToken("foo", "bar",
+ Arrays.asList(new SimpleGrantedAuthority("ROLE_USER")));
+
+ private BaseClientDetails client = new BaseClientDetails("foo", "resource", "scope", "token-exchange", "ROLE_USER");
+
+ @Mock
+ private AuthenticationManager authenticationManager;
+
+ private DefaultTokenServices providerTokenServices = new DefaultTokenServices();
+
+ private ClientDetailsService clientDetailsService = new ClientDetailsService() {
+ public ClientDetails loadClientByClientId(String clientId) throws OAuth2Exception {
+ return client;
+ }
+ };
+
+ private OAuth2RequestFactory requestFactory = new DefaultOAuth2RequestFactory(clientDetailsService);
+
+ private TokenExchangeTokenGranter granter;
+
+ private TokenRequest tokenRequest;
+
+ @Before
+ public void setup() {
+ when(this.authenticationManager.authenticate(any(TokenExchangeAuthenticationToken.class))).thenReturn(this.validUser);
+
+ String clientId = "client";
+ BaseClientDetails clientDetails = new BaseClientDetails();
+ clientDetails.setClientId(clientId);
+
+ providerTokenServices.setTokenStore(new InMemoryTokenStore());
+ Map parameters = new HashMap();
+ parameters.put("subject_token", "token123");
+ parameters.put("subject_type", "bearer");
+
+ granter = new TokenExchangeTokenGranter(authenticationManager,
+ providerTokenServices, clientDetailsService, requestFactory);
+
+ tokenRequest = requestFactory.createTokenRequest(parameters, clientDetails);
+ }
+
+ @Test
+ public void testSuccessfulGrant() {
+ OAuth2AccessToken token = granter.grant("token-exchange", tokenRequest);
+ OAuth2Authentication authentication = providerTokenServices.loadAuthentication(token.getValue());
+ assertTrue(authentication.isAuthenticated());
+ }
+
+ @Test(expected = InvalidClientException.class)
+ public void testGrantTypeNotSupported() {
+ client.setAuthorizedGrantTypes(Collections.singleton("client_credentials"));
+ granter.grant("token-exchange", tokenRequest);
+ }
+
+ @Test(expected = InvalidGrantException.class)
+ public void testInvalidToken() {
+ when(this.authenticationManager.authenticate(any(TokenExchangeAuthenticationToken.class))).thenThrow(new InvalidTokenException("invalid token"));
+ granter.grant("token-exchange", tokenRequest);
+ }
+
+ @Test(expected = InvalidGrantException.class)
+ public void testAccountLocked() {
+ when(this.authenticationManager.authenticate(any(TokenExchangeAuthenticationToken.class))).thenThrow(new LockedException("locked"));
+ granter.grant("token-exchange", tokenRequest);
+ }
+
+ @Test(expected = InvalidGrantException.class)
+ public void testUnauthenticated() {
+ validUser = new UsernamePasswordAuthenticationToken("foo", "bar");
+ when(this.authenticationManager.authenticate(any(TokenExchangeAuthenticationToken.class))).thenReturn(this.validUser);
+ granter.grant("token-exchange", tokenRequest);
+ }
+}
\ No newline at end of file
diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkDefinitionSourceTest.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkDefinitionSourceTest.java
new file mode 100644
index 000000000..75a545379
--- /dev/null
+++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkDefinitionSourceTest.java
@@ -0,0 +1,52 @@
+/*
+ * 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.security.oauth2.provider.token.store.jwk;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import java.net.URL;
+import java.util.Collections;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.when;
+import static org.powermock.api.mockito.PowerMockito.*;
+
+
+/**
+ * @author Joe Grandja
+ */
+@RunWith(PowerMockRunner.class)
+@PrepareForTest(JwkDefinitionSource.class)
+public class JwkDefinitionSourceTest {
+ private static final String DEFAULT_JWK_SET_URL = "https://identity.server1.io/token_keys";
+
+ @Test(expected = IllegalArgumentException.class)
+ public void constructorWhenInvalidJwkSetUrlThenThrowIllegalArgumentException() throws Exception {
+ new JwkDefinitionSource(DEFAULT_JWK_SET_URL.substring(1));
+ }
+
+ @Test
+ public void getDefinitionLoadIfNecessaryWhenKeyIdNotFoundThenLoadJwkDefinitions() throws Exception {
+ JwkDefinitionSource jwkDefinitionSource = spy(new JwkDefinitionSource(DEFAULT_JWK_SET_URL));
+ mockStatic(JwkDefinitionSource.class);
+ when(JwkDefinitionSource.loadJwkDefinitions(any(URL.class))).thenReturn(Collections.emptyMap());
+ jwkDefinitionSource.getDefinitionLoadIfNecessary("invalid-key-id");
+ verifyStatic();
+ }
+}
\ No newline at end of file
diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkDefinitionTest.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkDefinitionTest.java
new file mode 100644
index 000000000..a6ad3d2b2
--- /dev/null
+++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkDefinitionTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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.security.oauth2.provider.token.store.jwk;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Joe Grandja
+ */
+public class JwkDefinitionTest {
+
+ @Test
+ public void constructorWhenArgumentsPassedThenAttributesAreCorrectlySet() throws Exception {
+ String keyId = "key-id-1";
+ JwkDefinition.KeyType keyType = JwkDefinition.KeyType.RSA;
+ JwkDefinition.PublicKeyUse publicKeyUse = JwkDefinition.PublicKeyUse.SIG;
+ JwkDefinition.CryptoAlgorithm algorithm = JwkDefinition.CryptoAlgorithm.RS512;
+
+ JwkDefinition jwkDefinition = new JwkDefinition(keyId, keyType, publicKeyUse, algorithm) { };
+
+ assertEquals(keyId, jwkDefinition.getKeyId());
+ assertEquals(keyType, jwkDefinition.getKeyType());
+ assertEquals(publicKeyUse, jwkDefinition.getPublicKeyUse());
+ assertEquals(algorithm, jwkDefinition.getAlgorithm());
+ }
+
+ @Test
+ public void cryptoAlgorithmWhenAttributesAccessedThenCorrectValuesReturned() {
+ assertEquals("RS256", JwkDefinition.CryptoAlgorithm.RS256.headerParamValue());
+ assertEquals("SHA256withRSA", JwkDefinition.CryptoAlgorithm.RS256.standardName());
+ assertEquals("RS384", JwkDefinition.CryptoAlgorithm.RS384.headerParamValue());
+ assertEquals("SHA384withRSA", JwkDefinition.CryptoAlgorithm.RS384.standardName());
+ assertEquals("RS512", JwkDefinition.CryptoAlgorithm.RS512.headerParamValue());
+ assertEquals("SHA512withRSA", JwkDefinition.CryptoAlgorithm.RS512.standardName());
+ }
+}
\ No newline at end of file
diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkSetConverterTest.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkSetConverterTest.java
new file mode 100644
index 000000000..233385aeb
--- /dev/null
+++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkSetConverterTest.java
@@ -0,0 +1,284 @@
+/*
+ * 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.security.oauth2.provider.token.store.jwk;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import static org.junit.Assert.*;
+import static org.springframework.security.oauth2.provider.token.store.jwk.JwkAttributes.KEYS;
+
+/**
+ * @author Joe Grandja
+ */
+public class JwkSetConverterTest {
+ private final JwkSetConverter converter = new JwkSetConverter();
+ private final ObjectMapper objectMapper = new ObjectMapper();
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+
+ @Test
+ public void convertWhenJwkSetStreamIsNullThenThrowJwkException() throws Exception {
+ this.thrown.expect(JwkException.class);
+ this.thrown.expectMessage("Invalid JWK Set Object.");
+ this.converter.convert(null);
+ }
+
+ @Test
+ public void convertWhenJwkSetStreamIsEmptyThenThrowJwkException() throws Exception {
+ this.thrown.expect(JwkException.class);
+ this.thrown.expectMessage("Invalid JWK Set Object.");
+ this.converter.convert(new ByteArrayInputStream(new byte[0]));
+ }
+
+ @Test
+ public void convertWhenJwkSetStreamNotAnObjectThenThrowJwkException() throws Exception {
+ this.thrown.expect(JwkException.class);
+ this.thrown.expectMessage("Invalid JWK Set Object.");
+ this.converter.convert(new ByteArrayInputStream("".getBytes()));
+ }
+
+ @Test
+ public void convertWhenJwkSetStreamHasMissingKeysAttributeThenThrowJwkException() throws Exception {
+ this.thrown.expect(JwkException.class);
+ this.thrown.expectMessage("Invalid JWK Set Object.");
+ Map jwkSetObject = new HashMap();
+ this.converter.convert(this.asInputStream(jwkSetObject));
+ }
+
+ @Test
+ public void convertWhenJwkSetStreamHasInvalidKeysAttributeThenThrowJwkException() throws Exception {
+ this.thrown.expect(JwkException.class);
+ this.thrown.expectMessage("Invalid JWK Set Object. The JWK Set MUST have a keys attribute.");
+ Map jwkSetObject = new HashMap();
+ jwkSetObject.put(KEYS + "-invalid", new Map[0]);
+ this.converter.convert(this.asInputStream(jwkSetObject));
+ }
+
+ @Test
+ public void convertWhenJwkSetStreamHasInvalidJwkElementsThenThrowJwkException() throws Exception {
+ this.thrown.expect(JwkException.class);
+ this.thrown.expectMessage("Invalid JWK Set Object. The JWK Set MUST have an array of JWK(s).");
+ Map jwkSetObject = new HashMap();
+ jwkSetObject.put(JwkAttributes.KEYS, "");
+ this.converter.convert(this.asInputStream(jwkSetObject));
+ }
+
+ @Test
+ public void convertWhenJwkSetStreamHasEmptyJwkElementsThenReturnEmptyJwkSet() throws Exception {
+ Map jwkSetObject = new HashMap();
+ jwkSetObject.put(JwkAttributes.KEYS, new Map[0]);
+ Set jwkSet = this.converter.convert(this.asInputStream(jwkSetObject));
+ assertTrue("JWK Set NOT empty", jwkSet.isEmpty());
+ }
+
+ @Test
+ public void convertWhenJwkSetStreamHasEmptyJwkElementThenThrowJwkException() throws Exception {
+ this.thrown.expect(JwkException.class);
+ this.thrown.expectMessage("unknown (kty) is currently not supported.");
+ Map jwkSetObject = new HashMap();
+ Map jwkObject = new HashMap();
+ jwkSetObject.put(JwkAttributes.KEYS, new Map[] {jwkObject});
+ this.converter.convert(this.asInputStream(jwkSetObject));
+ }
+
+ @Test
+ public void convertWhenJwkSetStreamHasJwkElementWithECKeyTypeThenThrowJwkException() throws Exception {
+ this.thrown.expect(JwkException.class);
+ this.thrown.expectMessage("EC (kty) is currently not supported.");
+ Map jwkSetObject = new HashMap();
+ Map jwkObject = this.createJwkObject(JwkDefinition.KeyType.EC);
+ jwkSetObject.put(JwkAttributes.KEYS, new Map[] {jwkObject});
+ this.converter.convert(this.asInputStream(jwkSetObject));
+ }
+
+ @Test
+ public void convertWhenJwkSetStreamHasJwkElementWithOCTKeyTypeThenThrowJwkException() throws Exception {
+ this.thrown.expect(JwkException.class);
+ this.thrown.expectMessage("oct (kty) is currently not supported.");
+ Map jwkSetObject = new HashMap();
+ Map jwkObject = this.createJwkObject(JwkDefinition.KeyType.OCT);
+ jwkSetObject.put(JwkAttributes.KEYS, new Map[] {jwkObject});
+ this.converter.convert(this.asInputStream(jwkSetObject));
+ }
+
+ @Test
+ public void convertWhenJwkSetStreamHasJwkElementWithMissingKeyIdAttributeThenThrowJwkException() throws Exception {
+ this.thrown.expect(JwkException.class);
+ this.thrown.expectMessage("kid is a required attribute for a JWK.");
+ Map jwkSetObject = new HashMap();
+ Map jwkObject = this.createJwkObject(JwkDefinition.KeyType.RSA, null);
+ jwkSetObject.put(JwkAttributes.KEYS, new Map[] {jwkObject});
+ this.converter.convert(this.asInputStream(jwkSetObject));
+ }
+
+ @Test
+ public void convertWhenJwkSetStreamHasJwkElementWithMissingPublicKeyUseAttributeThenThrowJwkException() throws Exception {
+ this.thrown.expect(JwkException.class);
+ this.thrown.expectMessage("unknown (use) is currently not supported.");
+ Map jwkSetObject = new HashMap();
+ Map jwkObject = this.createJwkObject(JwkDefinition.KeyType.RSA, "key-id-1");
+ jwkSetObject.put(JwkAttributes.KEYS, new Map[] {jwkObject});
+ this.converter.convert(this.asInputStream(jwkSetObject));
+ }
+
+ @Test
+ public void convertWhenJwkSetStreamHasJwkElementWithENCPublicKeyUseAttributeThenThrowJwkException() throws Exception {
+ this.thrown.expect(JwkException.class);
+ this.thrown.expectMessage("enc (use) is currently not supported.");
+ Map jwkSetObject = new HashMap();
+ Map jwkObject = this.createJwkObject(JwkDefinition.KeyType.RSA, "key-id-1", JwkDefinition.PublicKeyUse.ENC);
+ jwkSetObject.put(JwkAttributes.KEYS, new Map[] {jwkObject});
+ this.converter.convert(this.asInputStream(jwkSetObject));
+ }
+
+ @Test
+ public void convertWhenJwkSetStreamHasJwkElementWithMissingAlgorithmAttributeThenThrowJwkException() throws Exception {
+ this.thrown.expect(JwkException.class);
+ this.thrown.expectMessage("unknown (alg) is currently not supported.");
+ Map jwkSetObject = new HashMap();
+ Map jwkObject = this.createJwkObject(JwkDefinition.KeyType.RSA, "key-id-1", JwkDefinition.PublicKeyUse.SIG);
+ jwkSetObject.put(JwkAttributes.KEYS, new Map[] {jwkObject});
+ this.converter.convert(this.asInputStream(jwkSetObject));
+ }
+
+ @Test
+ public void convertWhenJwkSetStreamHasJwkElementWithMissingRSAModulusAttributeThenThrowJwkException() throws Exception {
+ this.thrown.expect(JwkException.class);
+ this.thrown.expectMessage("n is a required attribute for a RSA JWK.");
+ Map jwkSetObject = new HashMap();
+ Map jwkObject = this.createJwkObject(JwkDefinition.KeyType.RSA, "key-id-1",
+ JwkDefinition.PublicKeyUse.SIG, JwkDefinition.CryptoAlgorithm.RS256);
+ jwkSetObject.put(JwkAttributes.KEYS, new Map[] {jwkObject});
+ this.converter.convert(this.asInputStream(jwkSetObject));
+ }
+
+ @Test
+ public void convertWhenJwkSetStreamHasJwkElementWithMissingRSAExponentAttributeThenThrowJwkException() throws Exception {
+ this.thrown.expect(JwkException.class);
+ this.thrown.expectMessage("e is a required attribute for a RSA JWK.");
+ Map jwkSetObject = new HashMap();
+ Map jwkObject = this.createJwkObject(JwkDefinition.KeyType.RSA, "key-id-1",
+ JwkDefinition.PublicKeyUse.SIG, JwkDefinition.CryptoAlgorithm.RS256, "AMh-pGAj9vX2gwFDyrXot1f2YfHgh8h0Qx6w9IqLL");
+ jwkSetObject.put(JwkAttributes.KEYS, new Map[] {jwkObject});
+ this.converter.convert(this.asInputStream(jwkSetObject));
+ }
+
+ @Test
+ public void convertWhenJwkSetStreamIsValidThenReturnJwkSet() throws Exception {
+ Map jwkSetObject = new HashMap();
+ Map jwkObject = this.createJwkObject(JwkDefinition.KeyType.RSA, "key-id-1",
+ JwkDefinition.PublicKeyUse.SIG, JwkDefinition.CryptoAlgorithm.RS256, "AMh-pGAj9vX2gwFDyrXot1f2YfHgh8h0Qx6w9IqLL", "AQAB");
+ jwkSetObject.put(JwkAttributes.KEYS, new Map[] {jwkObject});
+ Set jwkSet = this.converter.convert(this.asInputStream(jwkSetObject));
+ assertNotNull(jwkSet);
+ assertEquals("JWK Set NOT size=1", 1, jwkSet.size());
+
+ Map jwkObject2 = this.createJwkObject(JwkDefinition.KeyType.RSA, "key-id-2",
+ JwkDefinition.PublicKeyUse.SIG, JwkDefinition.CryptoAlgorithm.RS512, "AMh-pGAj9vX2gwFDyrXot1f2YfHgh8h0Qx6w9IqLL", "AQAB");
+ jwkSetObject.put(JwkAttributes.KEYS, new Map[] {jwkObject, jwkObject2});
+ jwkSet = this.converter.convert(this.asInputStream(jwkSetObject));
+ assertNotNull(jwkSet);
+ assertEquals("JWK Set NOT size=2", 2, jwkSet.size());
+ }
+
+ @Test
+ public void convertWhenJwkSetStreamHasDuplicateJwkElementsThenThrowJwkException() throws Exception {
+ this.thrown.expect(JwkException.class);
+ this.thrown.expectMessage("Duplicate JWK found in Set: key-id-1 (kid)");
+ Map jwkSetObject = new HashMap();
+ Map jwkObject = this.createJwkObject(JwkDefinition.KeyType.RSA, "key-id-1",
+ JwkDefinition.PublicKeyUse.SIG, JwkDefinition.CryptoAlgorithm.RS256, "AMh-pGAj9vX2gwFDyrXot1f2YfHgh8h0Qx6w9IqLL", "AQAB");
+ jwkSetObject.put(JwkAttributes.KEYS, new Map[] {jwkObject, jwkObject});
+ this.converter.convert(this.asInputStream(jwkSetObject));
+ }
+
+ private Map createJwkObject(JwkDefinition.KeyType keyType) {
+ return this.createJwkObject(keyType, null);
+ }
+
+ private Map createJwkObject(JwkDefinition.KeyType keyType, String keyId) {
+ return this.createJwkObject(keyType, keyId, null);
+ }
+
+ private Map createJwkObject(JwkDefinition.KeyType keyType,
+ String keyId,
+ JwkDefinition.PublicKeyUse publicKeyUse) {
+
+ return this.createJwkObject(keyType, keyId, publicKeyUse, null);
+ }
+
+ private Map createJwkObject(JwkDefinition.KeyType keyType,
+ String keyId,
+ JwkDefinition.PublicKeyUse publicKeyUse,
+ JwkDefinition.CryptoAlgorithm algorithm) {
+
+ return this.createJwkObject(keyType, keyId, publicKeyUse, algorithm, null);
+ }
+
+ private Map createJwkObject(JwkDefinition.KeyType keyType,
+ String keyId,
+ JwkDefinition.PublicKeyUse publicKeyUse,
+ JwkDefinition.CryptoAlgorithm algorithm,
+ String rsaModulus) {
+
+ return this.createJwkObject(keyType, keyId, publicKeyUse, algorithm, rsaModulus, null);
+ }
+
+ private Map createJwkObject(JwkDefinition.KeyType keyType,
+ String keyId,
+ JwkDefinition.PublicKeyUse publicKeyUse,
+ JwkDefinition.CryptoAlgorithm algorithm,
+ String rsaModulus,
+ String rsaExponent) {
+
+ Map jwkObject = new HashMap();
+ jwkObject.put(JwkAttributes.KEY_TYPE, keyType.value());
+ if (keyId != null) {
+ jwkObject.put(JwkAttributes.KEY_ID, keyId);
+ }
+ if (publicKeyUse != null) {
+ jwkObject.put(JwkAttributes.PUBLIC_KEY_USE, publicKeyUse.value());
+ }
+ if (algorithm != null) {
+ jwkObject.put(JwkAttributes.ALGORITHM, algorithm.headerParamValue());
+ }
+ if (rsaModulus != null) {
+ jwkObject.put(JwkAttributes.RSA_PUBLIC_KEY_MODULUS, rsaModulus);
+ }
+ if (rsaExponent != null) {
+ jwkObject.put(JwkAttributes.RSA_PUBLIC_KEY_EXPONENT, rsaExponent);
+ }
+ return jwkObject;
+ }
+
+ private InputStream asInputStream(Map content) throws Exception {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ this.objectMapper.writeValue(out, content);
+ return new ByteArrayInputStream(out.toByteArray());
+ }
+}
\ No newline at end of file
diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkTokenStoreTest.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkTokenStoreTest.java
new file mode 100644
index 000000000..28ea3b528
--- /dev/null
+++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkTokenStoreTest.java
@@ -0,0 +1,153 @@
+/*
+ * 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.security.oauth2.provider.token.store.jwk;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.springframework.security.oauth2.common.OAuth2AccessToken;
+import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
+import org.springframework.util.ReflectionUtils;
+
+import java.lang.reflect.Field;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.*;
+import static org.powermock.api.mockito.PowerMockito.spy;
+
+
+/**
+ * @author Joe Grandja
+ */
+@RunWith(PowerMockRunner.class)
+@PrepareForTest(JwkTokenStore.class)
+public class JwkTokenStoreTest {
+ private JwkTokenStore jwkTokenStore = new JwkTokenStore("https://identity.server1.io/token_keys");
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void readAuthenticationUsingOAuth2AccessTokenWhenCalledThenDelegateCalled() throws Exception {
+ JwkTokenStore spy = spy(this.jwkTokenStore);
+ JwtTokenStore delegate = mock(JwtTokenStore.class);
+ when(delegate.readAuthentication(any(OAuth2AccessToken.class))).thenReturn(null);
+
+ Field field = ReflectionUtils.findField(spy.getClass(), "delegate");
+ field.setAccessible(true);
+ ReflectionUtils.setField(field, spy, delegate);
+
+ spy.readAuthentication(mock(OAuth2AccessToken.class));
+ verify(delegate).readAuthentication(any(OAuth2AccessToken.class));
+ }
+
+ @Test
+ public void readAuthenticationUsingAccessTokenStringWhenCalledThenDelegateCalled() throws Exception {
+ JwkTokenStore spy = spy(this.jwkTokenStore);
+ JwtTokenStore delegate = mock(JwtTokenStore.class);
+ when(delegate.readAuthentication(anyString())).thenReturn(null);
+
+ Field field = ReflectionUtils.findField(spy.getClass(), "delegate");
+ field.setAccessible(true);
+ ReflectionUtils.setField(field, spy, delegate);
+
+ spy.readAuthentication(anyString());
+ verify(delegate).readAuthentication(anyString());
+ }
+
+ @Test
+ public void readAccessTokenWhenCalledThenDelegateCalled() throws Exception {
+ JwkTokenStore spy = spy(this.jwkTokenStore);
+ JwtTokenStore delegate = mock(JwtTokenStore.class);
+ when(delegate.readAccessToken(anyString())).thenReturn(null);
+
+ Field field = ReflectionUtils.findField(spy.getClass(), "delegate");
+ field.setAccessible(true);
+ ReflectionUtils.setField(field, spy, delegate);
+
+ spy.readAccessToken(anyString());
+ verify(delegate).readAccessToken(anyString());
+ }
+
+ @Test
+ public void storeAccessTokenWhenCalledThenThrowJwkException() throws Exception {
+ this.setUpExpectedJwkException();
+ this.jwkTokenStore.storeAccessToken(null, null);
+ }
+
+ @Test
+ public void removeAccessTokenWhenCalledThenThrowJwkException() throws Exception {
+ this.setUpExpectedJwkException();
+ this.jwkTokenStore.removeAccessToken(null);
+ }
+
+ @Test
+ public void storeRefreshTokenWhenCalledThenThrowJwkException() throws Exception {
+ this.setUpExpectedJwkException();
+ this.jwkTokenStore.storeRefreshToken(null, null);
+ }
+
+ @Test
+ public void readRefreshTokenWhenCalledThenThrowJwkException() throws Exception {
+ this.setUpExpectedJwkException();
+ this.jwkTokenStore.readRefreshToken(null);
+ }
+
+ @Test
+ public void readAuthenticationForRefreshTokenWhenCalledThenThrowJwkException() throws Exception {
+ this.setUpExpectedJwkException();
+ this.jwkTokenStore.readAuthenticationForRefreshToken(null);
+ }
+
+ @Test
+ public void removeRefreshTokenWhenCalledThenThrowJwkException() throws Exception {
+ this.setUpExpectedJwkException();
+ this.jwkTokenStore.removeRefreshToken(null);
+ }
+
+ @Test
+ public void removeAccessTokenUsingRefreshTokenWhenCalledThenThrowJwkException() throws Exception {
+ this.setUpExpectedJwkException();
+ this.jwkTokenStore.removeAccessTokenUsingRefreshToken(null);
+ }
+
+ @Test
+ public void getAccessTokenWhenCalledThenThrowJwkException() throws Exception {
+ this.setUpExpectedJwkException();
+ this.jwkTokenStore.getAccessToken(null);
+ }
+
+ @Test
+ public void findTokensByClientIdAndUserNameWhenCalledThenThrowJwkException() throws Exception {
+ this.setUpExpectedJwkException();
+ this.jwkTokenStore.findTokensByClientIdAndUserName(null, null);
+ }
+
+ @Test
+ public void findTokensByClientIdWhenCalledThenThrowJwkException() throws Exception {
+ this.setUpExpectedJwkException();
+ this.jwkTokenStore.findTokensByClientId(null);
+ }
+
+ private void setUpExpectedJwkException() {
+ this.thrown.expect(JwkException.class);
+ this.thrown.expectMessage("This operation is not supported.");
+ }
+}
\ No newline at end of file
diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkVerifyingJwtAccessTokenConverterTest.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkVerifyingJwtAccessTokenConverterTest.java
new file mode 100644
index 000000000..3c830838e
--- /dev/null
+++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/jwk/JwkVerifyingJwtAccessTokenConverterTest.java
@@ -0,0 +1,109 @@
+/*
+ * 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.security.oauth2.provider.token.store.jwk;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.springframework.security.oauth2.provider.token.store.jwk.JwtTestUtil.createJwt;
+import static org.springframework.security.oauth2.provider.token.store.jwk.JwtTestUtil.createJwtHeader;
+
+/**
+ * @author Joe Grandja
+ */
+public class JwkVerifyingJwtAccessTokenConverterTest {
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void encodeWhenCalledThenThrowJwkException() throws Exception {
+ this.thrown.expect(JwkException.class);
+ this.thrown.expectMessage("JWT signing (JWS) is not supported.");
+ JwkVerifyingJwtAccessTokenConverter accessTokenConverter =
+ new JwkVerifyingJwtAccessTokenConverter(mock(JwkDefinitionSource.class));
+ accessTokenConverter.encode(null, null);
+ }
+
+ @Test
+ public void decodeWhenKeyIdHeaderMissingThenThrowJwkException() throws Exception {
+ this.thrown.expect(InvalidTokenException.class);
+ this.thrown.expectMessage("Invalid JWT/JWS: kid is a required JOSE Header");
+ JwkVerifyingJwtAccessTokenConverter accessTokenConverter =
+ new JwkVerifyingJwtAccessTokenConverter(mock(JwkDefinitionSource.class));
+ String jwt = createJwt(createJwtHeader(null, JwkDefinition.CryptoAlgorithm.RS256));
+ accessTokenConverter.decode(jwt);
+ }
+
+ @Test
+ public void decodeWhenKeyIdHeaderInvalidThenThrowJwkException() throws Exception {
+ this.thrown.expect(InvalidTokenException.class);
+ this.thrown.expectMessage("Invalid JOSE Header kid (invalid-key-id)");
+ JwkDefinition jwkDefinition = this.createRSAJwkDefinition("key-id-1", JwkDefinition.CryptoAlgorithm.RS256);
+ JwkDefinitionSource jwkDefinitionSource = mock(JwkDefinitionSource.class);
+ when(jwkDefinitionSource.getDefinitionLoadIfNecessary("key-id-1")).thenReturn(jwkDefinition);
+ JwkVerifyingJwtAccessTokenConverter accessTokenConverter =
+ new JwkVerifyingJwtAccessTokenConverter(jwkDefinitionSource);
+ String jwt = createJwt(createJwtHeader("invalid-key-id", JwkDefinition.CryptoAlgorithm.RS256));
+ accessTokenConverter.decode(jwt);
+ }
+
+ @Test
+ public void decodeWhenAlgorithmHeaderMissingThenThrowJwkException() throws Exception {
+ this.thrown.expect(InvalidTokenException.class);
+ this.thrown.expectMessage("Invalid JWT/JWS: alg is a required JOSE Header");
+ JwkDefinition jwkDefinition = this.createRSAJwkDefinition("key-id-1", JwkDefinition.CryptoAlgorithm.RS256);
+ JwkDefinitionSource jwkDefinitionSource = mock(JwkDefinitionSource.class);
+ when(jwkDefinitionSource.getDefinitionLoadIfNecessary("key-id-1")).thenReturn(jwkDefinition);
+ JwkVerifyingJwtAccessTokenConverter accessTokenConverter =
+ new JwkVerifyingJwtAccessTokenConverter(jwkDefinitionSource);
+ String jwt = createJwt(createJwtHeader("key-id-1", null));
+ accessTokenConverter.decode(jwt);
+ }
+
+ @Test
+ public void decodeWhenAlgorithmHeaderDoesNotMatchJwkAlgorithmThenThrowJwkException() throws Exception {
+ this.thrown.expect(InvalidTokenException.class);
+ this.thrown.expectMessage("Invalid JOSE Header alg (RS512) " +
+ "does not match algorithm associated to JWK with kid (key-id-1)");
+ JwkDefinition jwkDefinition = this.createRSAJwkDefinition("key-id-1", JwkDefinition.CryptoAlgorithm.RS256);
+ JwkDefinitionSource jwkDefinitionSource = mock(JwkDefinitionSource.class);
+ when(jwkDefinitionSource.getDefinitionLoadIfNecessary("key-id-1")).thenReturn(jwkDefinition);
+ JwkVerifyingJwtAccessTokenConverter accessTokenConverter =
+ new JwkVerifyingJwtAccessTokenConverter(jwkDefinitionSource);
+ String jwt = createJwt(createJwtHeader("key-id-1", JwkDefinition.CryptoAlgorithm.RS512));
+ accessTokenConverter.decode(jwt);
+ }
+
+ private JwkDefinition createRSAJwkDefinition(String keyId, JwkDefinition.CryptoAlgorithm algorithm) {
+ return createRSAJwkDefinition(JwkDefinition.KeyType.RSA, keyId,
+ JwkDefinition.PublicKeyUse.SIG, algorithm, "AMh-pGAj9vX2gwFDyrXot1f2YfHgh8h0Qx6w9IqLL", "AQAB");
+ }
+
+ private JwkDefinition createRSAJwkDefinition(JwkDefinition.KeyType keyType,
+ String keyId,
+ JwkDefinition.PublicKeyUse publicKeyUse,
+ JwkDefinition.CryptoAlgorithm algorithm,
+ String modulus,
+ String exponent) {
+
+ return new RsaJwkDefinition(keyId, publicKeyUse, algorithm, modulus, exponent);
+ }
+}
\ No newline at end of file
diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/jwk/JwtHeaderConverterTest.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/jwk/JwtHeaderConverterTest.java
new file mode 100644
index 000000000..a7689d5c3
--- /dev/null
+++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/jwk/JwtHeaderConverterTest.java
@@ -0,0 +1,58 @@
+/*
+ * 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.security.oauth2.provider.token.store.jwk;
+
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
+
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.springframework.security.oauth2.provider.token.store.jwk.JwtTestUtil.createJwt;
+
+/**
+ * @author Joe Grandja
+ */
+public class JwtHeaderConverterTest {
+ private final JwtHeaderConverter converter = new JwtHeaderConverter();
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+
+ @Test
+ public void convertWhenJwtTokenIsNullThenThrowNullPointerException() throws Exception {
+ this.thrown.expect(NullPointerException.class);
+ this.converter.convert(null);
+ }
+
+ @Test
+ public void convertWhenJwtTokenInvalidThenThrowJwkException() throws Exception {
+ this.thrown.expect(InvalidTokenException.class);
+ this.thrown.expectMessage("Invalid JWT. Missing JOSE Header.");
+ this.converter.convert("");
+ }
+
+ @Test
+ public void convertWhenJwtTokenValidThenReturnJwtHeaders() throws Exception {
+ Map jwtHeaders = this.converter.convert(createJwt());
+ assertEquals("key-id-1", jwtHeaders.get(JwkAttributes.KEY_ID));
+ assertEquals(JwkDefinition.CryptoAlgorithm.RS256.headerParamValue(), jwtHeaders.get(JwkAttributes.ALGORITHM));
+ }
+}
\ No newline at end of file
diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/jwk/JwtTestUtil.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/jwk/JwtTestUtil.java
new file mode 100644
index 000000000..5aab5d5e9
--- /dev/null
+++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/jwk/JwtTestUtil.java
@@ -0,0 +1,86 @@
+/*
+ * 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.security.oauth2.provider.token.store.jwk;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.security.jwt.codec.Codecs;
+
+import java.io.ByteArrayOutputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Joe Grandja
+ */
+class JwtTestUtil {
+ private static final ObjectMapper objectMapper = new ObjectMapper();
+
+ static String createJwt() throws Exception {
+ return createJwt(createDefaultJwtHeader());
+ }
+
+ static String createJwt(byte[] jwtHeader) throws Exception {
+ return createJwt(jwtHeader, createDefaultJwtPayload());
+ }
+
+ static String createJwt(byte[] jwtHeader, byte[] jwtPayload) throws Exception {
+ byte[] encodedJwtHeader = Codecs.b64UrlEncode(jwtHeader);
+ byte[] encodedJwtPayload = Codecs.b64UrlEncode(jwtPayload);
+ byte[] period = Codecs.utf8Encode(".");
+ return new String(join(encodedJwtHeader, period, encodedJwtPayload));
+ }
+
+ static byte[] createDefaultJwtHeader() throws Exception {
+ return createJwtHeader("key-id-1", JwkDefinition.CryptoAlgorithm.RS256);
+ }
+
+ static byte[] createJwtHeader(String keyId, JwkDefinition.CryptoAlgorithm algorithm) throws Exception {
+ Map jwtHeader = new HashMap();
+ if (keyId != null) {
+ jwtHeader.put(JwkAttributes.KEY_ID, keyId);
+ }
+ if (algorithm != null) {
+ jwtHeader.put(JwkAttributes.ALGORITHM, algorithm.headerParamValue());
+ }
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ objectMapper.writeValue(out, jwtHeader);
+ return out.toByteArray();
+ }
+
+ static byte[] createDefaultJwtPayload() throws Exception {
+ Map jwtPayload = new HashMap();
+ jwtPayload.put("claim-name-1", "claim-value-1");
+ jwtPayload.put("claim-name-2", "claim-value-2");
+ jwtPayload.put("claim-name-3", "claim-value-3");
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ objectMapper.writeValue(out, jwtPayload);
+ return out.toByteArray();
+ }
+
+ private static byte[] join(byte[]... byteArrays) {
+ int size = 0;
+ for (byte[] bytes : byteArrays) {
+ size += bytes.length;
+ }
+ byte[] result = new byte[size];
+ int index = 0;
+ for (byte[] bytes : byteArrays) {
+ System.arraycopy(bytes, 0, result, index, bytes.length);
+ index += bytes.length;
+ }
+ return result;
+ }
+}
\ No newline at end of file
diff --git a/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/jwk/RsaJwkDefinitionTest.java b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/jwk/RsaJwkDefinitionTest.java
new file mode 100644
index 000000000..72ca34d3c
--- /dev/null
+++ b/spring-security-oauth2/src/test/java/org/springframework/security/oauth2/provider/token/store/jwk/RsaJwkDefinitionTest.java
@@ -0,0 +1,45 @@
+/*
+ * 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.security.oauth2.provider.token.store.jwk;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Joe Grandja
+ */
+public class RsaJwkDefinitionTest {
+
+ @Test
+ public void constructorWhenArgumentsPassedThenAttributesAreCorrectlySet() throws Exception {
+ String keyId = "key-id-1";
+ JwkDefinition.PublicKeyUse publicKeyUse = JwkDefinition.PublicKeyUse.ENC;
+ JwkDefinition.CryptoAlgorithm algorithm = JwkDefinition.CryptoAlgorithm.RS384;
+ String modulus = "AMh-pGAj9vX2gwFDyrXot1f2YfHgh8h0Qx6w9IqLL";
+ String exponent = "AQAB";
+
+ RsaJwkDefinition rsaJwkDefinition = new RsaJwkDefinition(
+ keyId, publicKeyUse, algorithm, modulus, exponent);
+
+ assertEquals(keyId, rsaJwkDefinition.getKeyId());
+ assertEquals(JwkDefinition.KeyType.RSA, rsaJwkDefinition.getKeyType());
+ assertEquals(publicKeyUse, rsaJwkDefinition.getPublicKeyUse());
+ assertEquals(algorithm, rsaJwkDefinition.getAlgorithm());
+ assertEquals(modulus, rsaJwkDefinition.getModulus());
+ assertEquals(exponent, rsaJwkDefinition.getExponent());
+ }
+}
\ No newline at end of file
diff --git a/tests/annotation/approval/pom.xml b/tests/annotation/approval/pom.xml
index 2dc67ad4d..d1110a48a 100644
--- a/tests/annotation/approval/pom.xml
+++ b/tests/annotation/approval/pom.xml
@@ -10,7 +10,7 @@
org.demo
spring-oauth2-tests-parent
- 2.0.13.BUILD-SNAPSHOT
+ 2.1.1.BUILD-SNAPSHOT
diff --git a/tests/annotation/approval/src/main/java/demo/Application.java b/tests/annotation/approval/src/main/java/demo/Application.java
index 101b9bfb8..82281f84a 100644
--- a/tests/annotation/approval/src/main/java/demo/Application.java
+++ b/tests/annotation/approval/src/main/java/demo/Application.java
@@ -2,9 +2,8 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
@@ -19,9 +18,7 @@
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
-@Configuration
-@ComponentScan
-@EnableAutoConfiguration
+@SpringBootApplication
@EnableResourceServer
@RestController
public class Application {
diff --git a/tests/annotation/approval/src/main/resources/application.yml b/tests/annotation/approval/src/main/resources/application.yml
index e52b05d1f..99c539833 100644
--- a/tests/annotation/approval/src/main/resources/application.yml
+++ b/tests/annotation/approval/src/main/resources/application.yml
@@ -6,3 +6,6 @@ management:
security:
user:
password: password
+ oauth2:
+ resource:
+ filter-order: 3
diff --git a/tests/annotation/approval/src/test/java/demo/ApplicationTests.java b/tests/annotation/approval/src/test/java/demo/ApplicationTests.java
index 15eca8da6..39d23f056 100644
--- a/tests/annotation/approval/src/test/java/demo/ApplicationTests.java
+++ b/tests/annotation/approval/src/test/java/demo/ApplicationTests.java
@@ -2,15 +2,12 @@
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.springframework.boot.test.IntegrationTest;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import org.springframework.test.context.web.WebAppConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
+import org.springframework.test.context.junit4.SpringRunner;
-@RunWith(SpringJUnit4ClassRunner.class)
-@SpringApplicationConfiguration(classes = Application.class)
-@WebAppConfiguration
-@IntegrationTest("server.port=0")
+@RunWith(SpringRunner.class)
+@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)
public class ApplicationTests {
@Test
diff --git a/tests/annotation/approval/src/test/java/demo/AuthorizationCodeProviderTests.java b/tests/annotation/approval/src/test/java/demo/AuthorizationCodeProviderTests.java
index 3bc5e7dac..7b60325b0 100755
--- a/tests/annotation/approval/src/test/java/demo/AuthorizationCodeProviderTests.java
+++ b/tests/annotation/approval/src/test/java/demo/AuthorizationCodeProviderTests.java
@@ -14,14 +14,11 @@
import static org.junit.Assert.assertTrue;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-
import sparklr.common.AbstractAuthorizationCodeProviderTests;
/**
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes = Application.class)
public class AuthorizationCodeProviderTests extends AbstractAuthorizationCodeProviderTests {
protected void verifyAuthorizationPage(String page) {
diff --git a/tests/annotation/approval/src/test/java/demo/ClientCredentialsProviderTests.java b/tests/annotation/approval/src/test/java/demo/ClientCredentialsProviderTests.java
index af8190074..857ff7fa0 100644
--- a/tests/annotation/approval/src/test/java/demo/ClientCredentialsProviderTests.java
+++ b/tests/annotation/approval/src/test/java/demo/ClientCredentialsProviderTests.java
@@ -1,13 +1,10 @@
package demo;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-
import sparklr.common.AbstractClientCredentialsProviderTests;
/**
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes=Application.class)
public class ClientCredentialsProviderTests extends AbstractClientCredentialsProviderTests {
diff --git a/tests/annotation/approval/src/test/java/demo/ImplicitProviderTests.java b/tests/annotation/approval/src/test/java/demo/ImplicitProviderTests.java
index 7a8958187..0e34ccc7d 100644
--- a/tests/annotation/approval/src/test/java/demo/ImplicitProviderTests.java
+++ b/tests/annotation/approval/src/test/java/demo/ImplicitProviderTests.java
@@ -1,13 +1,10 @@
package demo;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-
import sparklr.common.AbstractImplicitProviderTests;
/**
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes=Application.class)
public class ImplicitProviderTests extends AbstractImplicitProviderTests {
}
diff --git a/tests/annotation/approval/src/test/java/demo/ProtectedResourceTests.java b/tests/annotation/approval/src/test/java/demo/ProtectedResourceTests.java
index c752cbe12..302b30f96 100644
--- a/tests/annotation/approval/src/test/java/demo/ProtectedResourceTests.java
+++ b/tests/annotation/approval/src/test/java/demo/ProtectedResourceTests.java
@@ -13,15 +13,12 @@
package demo;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-
import sparklr.common.AbstractProtectedResourceTests;
/**
* @author Dave Syer
*
*/
-@SpringApplicationConfiguration(classes = Application.class)
public class ProtectedResourceTests extends AbstractProtectedResourceTests {
}
diff --git a/tests/annotation/approval/src/test/java/demo/RefreshTokenSupportTests.java b/tests/annotation/approval/src/test/java/demo/RefreshTokenSupportTests.java
index 4ed370eea..417bac867 100644
--- a/tests/annotation/approval/src/test/java/demo/RefreshTokenSupportTests.java
+++ b/tests/annotation/approval/src/test/java/demo/RefreshTokenSupportTests.java
@@ -1,13 +1,10 @@
package demo;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-
import sparklr.common.AbstractRefreshTokenSupportTests;
/**
* @author Ryan Heaton
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes=Application.class)
public class RefreshTokenSupportTests extends AbstractRefreshTokenSupportTests {
}
diff --git a/tests/annotation/approval/src/test/java/demo/ResourceOwnerPasswordProviderTests.java b/tests/annotation/approval/src/test/java/demo/ResourceOwnerPasswordProviderTests.java
index aa5786098..5682e05a6 100644
--- a/tests/annotation/approval/src/test/java/demo/ResourceOwnerPasswordProviderTests.java
+++ b/tests/annotation/approval/src/test/java/demo/ResourceOwnerPasswordProviderTests.java
@@ -1,13 +1,10 @@
package demo;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-
import sparklr.common.AbstractResourceOwnerPasswordProviderTests;
/**
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes=Application.class)
public class ResourceOwnerPasswordProviderTests extends AbstractResourceOwnerPasswordProviderTests {
}
diff --git a/tests/annotation/client/pom.xml b/tests/annotation/client/pom.xml
index 555854c6d..d2aebd623 100644
--- a/tests/annotation/client/pom.xml
+++ b/tests/annotation/client/pom.xml
@@ -11,7 +11,7 @@
org.demo
spring-oauth2-tests-parent
- 2.0.13.BUILD-SNAPSHOT
+ 2.1.1.BUILD-SNAPSHOT
diff --git a/tests/annotation/client/src/main/resources/application.yml b/tests/annotation/client/src/main/resources/application.yml
index 72f3eb459..e223ea3ad 100644
--- a/tests/annotation/client/src/main/resources/application.yml
+++ b/tests/annotation/client/src/main/resources/application.yml
@@ -8,3 +8,6 @@ server:
security:
basic:
enabled: false
+ oauth2:
+ resource:
+ filter-order: 3
diff --git a/tests/annotation/client/src/test/java/client/ApplicationTests.java b/tests/annotation/client/src/test/java/client/ApplicationTests.java
index 8c5aef34a..971e2b4a0 100644
--- a/tests/annotation/client/src/test/java/client/ApplicationTests.java
+++ b/tests/annotation/client/src/test/java/client/ApplicationTests.java
@@ -2,15 +2,12 @@
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.springframework.boot.test.IntegrationTest;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import org.springframework.test.context.web.WebAppConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
+import org.springframework.test.context.junit4.SpringRunner;
-@RunWith(SpringJUnit4ClassRunner.class)
-@SpringApplicationConfiguration(classes = ClientApplication.class)
-@WebAppConfiguration
-@IntegrationTest("server.port=0")
+@RunWith(SpringRunner.class)
+@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT, classes=ClientApplication.class)
public class ApplicationTests {
@Test
diff --git a/tests/annotation/client/src/test/java/client/ClientServerInteractionTests.java b/tests/annotation/client/src/test/java/client/ClientServerInteractionTests.java
index 64db5054c..f078ff6e3 100644
--- a/tests/annotation/client/src/test/java/client/ClientServerInteractionTests.java
+++ b/tests/annotation/client/src/test/java/client/ClientServerInteractionTests.java
@@ -6,7 +6,8 @@
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.SpringApplicationConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.security.oauth2.client.DefaultOAuth2ClientContext;
import org.springframework.security.oauth2.client.OAuth2RestOperations;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
@@ -19,7 +20,8 @@
/**
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes = { ClientApplication.class, CombinedApplication.class })
+@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, classes = {
+ ClientApplication.class, CombinedApplication.class })
@ActiveProfiles("combined")
public class ClientServerInteractionTests extends AbstractIntegrationTests {
@@ -27,7 +29,7 @@ public class ClientServerInteractionTests extends AbstractIntegrationTests {
private AuthorizationCodeResourceDetails resource;
private OAuth2RestOperations template;
-
+
@Before
public void init() {
template = new OAuth2RestTemplate(resource, new DefaultOAuth2ClientContext());
diff --git a/tests/annotation/common/pom.xml b/tests/annotation/common/pom.xml
index 6491f1938..dc24d1048 100644
--- a/tests/annotation/common/pom.xml
+++ b/tests/annotation/common/pom.xml
@@ -10,7 +10,7 @@
org.demo
spring-oauth2-tests-parent
- 2.0.13.BUILD-SNAPSHOT
+ 2.1.1.BUILD-SNAPSHOT
@@ -53,15 +53,6 @@
demo.Application
-
-
-
- org.springframework.boot
- spring-boot-maven-plugin
-
-
-
-
spring-snapshots
diff --git a/tests/annotation/common/src/main/java/sparklr/common/AbstractIntegrationTests.java b/tests/annotation/common/src/main/java/sparklr/common/AbstractIntegrationTests.java
index b35341615..023566427 100644
--- a/tests/annotation/common/src/main/java/sparklr/common/AbstractIntegrationTests.java
+++ b/tests/annotation/common/src/main/java/sparklr/common/AbstractIntegrationTests.java
@@ -31,7 +31,9 @@
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.boot.autoconfigure.web.ServerProperties;
-import org.springframework.boot.test.IntegrationTest;
+import org.springframework.boot.context.embedded.LocalServerPort;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.converter.HttpMessageConverter;
@@ -53,12 +55,10 @@
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;
import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import org.springframework.test.context.web.WebAppConfiguration;
+import org.springframework.test.context.junit4.SpringRunner;
-@RunWith(SpringJUnit4ClassRunner.class)
-@WebAppConfiguration
-@IntegrationTest("server.port=0")
+@RunWith(SpringRunner.class)
+@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)
public abstract class AbstractIntegrationTests {
public static final String JAVAX_NET_SSL_TRUST_STORE_PASSWORD = "javax.net.ssl.trustStorePassword";
@@ -84,7 +84,7 @@ public abstract class AbstractIntegrationTests {
}
}
- @Value("${local.server.port}")
+ @LocalServerPort
private int port;
@Rule
diff --git a/tests/annotation/common/src/main/java/sparklr/common/HttpTestUtils.java b/tests/annotation/common/src/main/java/sparklr/common/HttpTestUtils.java
index 8e765c04c..1a0456552 100644
--- a/tests/annotation/common/src/main/java/sparklr/common/HttpTestUtils.java
+++ b/tests/annotation/common/src/main/java/sparklr/common/HttpTestUtils.java
@@ -9,7 +9,7 @@
import org.junit.rules.MethodRule;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.Statement;
-import org.springframework.boot.test.TestRestTemplate;
+import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
@@ -234,7 +234,7 @@ public RestOperations getRestTemplate() {
}
public RestOperations createRestTemplate() {
- RestTemplate client = new TestRestTemplate();
+ RestTemplate client = new TestRestTemplate().getRestTemplate();
return client;
}
diff --git a/tests/annotation/custom-authentication/pom.xml b/tests/annotation/custom-authentication/pom.xml
index f2f8cb481..38884d6b4 100644
--- a/tests/annotation/custom-authentication/pom.xml
+++ b/tests/annotation/custom-authentication/pom.xml
@@ -10,7 +10,7 @@
org.demo
spring-oauth2-tests-parent
- 2.0.13.BUILD-SNAPSHOT
+ 2.1.1.BUILD-SNAPSHOT
diff --git a/tests/annotation/custom-authentication/src/main/java/demo/Application.java b/tests/annotation/custom-authentication/src/main/java/demo/Application.java
index 8566b7eb1..b45985dc4 100644
--- a/tests/annotation/custom-authentication/src/main/java/demo/Application.java
+++ b/tests/annotation/custom-authentication/src/main/java/demo/Application.java
@@ -2,7 +2,7 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.AuthenticationManager;
@@ -19,8 +19,7 @@
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
-@Configuration
-@EnableAutoConfiguration
+@SpringBootApplication
@EnableResourceServer
@RestController
public class Application {
diff --git a/tests/annotation/custom-authentication/src/main/resources/application.yml b/tests/annotation/custom-authentication/src/main/resources/application.yml
index ccf06f8ba..8f7a77341 100644
--- a/tests/annotation/custom-authentication/src/main/resources/application.yml
+++ b/tests/annotation/custom-authentication/src/main/resources/application.yml
@@ -6,6 +6,9 @@ management:
security:
user:
password: password
+ oauth2:
+ resource:
+ filter-order: 3
logging:
level:
# org.springframework.security: DEBUG
\ No newline at end of file
diff --git a/tests/annotation/custom-authentication/src/test/java/demo/ApplicationTests.java b/tests/annotation/custom-authentication/src/test/java/demo/ApplicationTests.java
index 15eca8da6..1f2353d99 100644
--- a/tests/annotation/custom-authentication/src/test/java/demo/ApplicationTests.java
+++ b/tests/annotation/custom-authentication/src/test/java/demo/ApplicationTests.java
@@ -2,15 +2,11 @@
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.springframework.boot.test.IntegrationTest;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import org.springframework.test.context.web.WebAppConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
-@RunWith(SpringJUnit4ClassRunner.class)
-@SpringApplicationConfiguration(classes = Application.class)
-@WebAppConfiguration
-@IntegrationTest("server.port=0")
+@RunWith(SpringRunner.class)
+@SpringBootTest
public class ApplicationTests {
@Test
diff --git a/tests/annotation/custom-authentication/src/test/java/demo/ClientCredentialsProviderTests.java b/tests/annotation/custom-authentication/src/test/java/demo/ClientCredentialsProviderTests.java
index f4dd6da46..f0734bc81 100644
--- a/tests/annotation/custom-authentication/src/test/java/demo/ClientCredentialsProviderTests.java
+++ b/tests/annotation/custom-authentication/src/test/java/demo/ClientCredentialsProviderTests.java
@@ -9,7 +9,6 @@
import org.junit.Before;
import org.junit.Test;
-import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
@@ -30,7 +29,6 @@
*
* @author michaeltecourt
*/
-@SpringApplicationConfiguration(classes = Application.class)
public class ClientCredentialsProviderTests extends AbstractClientCredentialsProviderTests {
protected URI tokenUri;
diff --git a/tests/annotation/custom-grant/pom.xml b/tests/annotation/custom-grant/pom.xml
index 3ef3ac2de..648084bea 100644
--- a/tests/annotation/custom-grant/pom.xml
+++ b/tests/annotation/custom-grant/pom.xml
@@ -10,7 +10,7 @@
org.demo
spring-oauth2-tests-parent
- 2.0.13.BUILD-SNAPSHOT
+ 2.1.1.BUILD-SNAPSHOT
diff --git a/tests/annotation/custom-grant/src/main/java/demo/Application.java b/tests/annotation/custom-grant/src/main/java/demo/Application.java
index 7dd777944..df08bbfe9 100644
--- a/tests/annotation/custom-grant/src/main/java/demo/Application.java
+++ b/tests/annotation/custom-grant/src/main/java/demo/Application.java
@@ -6,7 +6,7 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.AuthenticationManager;
@@ -24,8 +24,7 @@
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
-@Configuration
-@EnableAutoConfiguration
+@SpringBootApplication
@EnableResourceServer
@RestController
public class Application {
diff --git a/tests/annotation/custom-grant/src/main/resources/application.yml b/tests/annotation/custom-grant/src/main/resources/application.yml
index ccf06f8ba..8f7a77341 100644
--- a/tests/annotation/custom-grant/src/main/resources/application.yml
+++ b/tests/annotation/custom-grant/src/main/resources/application.yml
@@ -6,6 +6,9 @@ management:
security:
user:
password: password
+ oauth2:
+ resource:
+ filter-order: 3
logging:
level:
# org.springframework.security: DEBUG
\ No newline at end of file
diff --git a/tests/annotation/custom-grant/src/test/java/demo/ApplicationTests.java b/tests/annotation/custom-grant/src/test/java/demo/ApplicationTests.java
index 15eca8da6..34f49b849 100644
--- a/tests/annotation/custom-grant/src/test/java/demo/ApplicationTests.java
+++ b/tests/annotation/custom-grant/src/test/java/demo/ApplicationTests.java
@@ -2,15 +2,11 @@
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.springframework.boot.test.IntegrationTest;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import org.springframework.test.context.web.WebAppConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
-@RunWith(SpringJUnit4ClassRunner.class)
-@SpringApplicationConfiguration(classes = Application.class)
-@WebAppConfiguration
-@IntegrationTest("server.port=0")
+@RunWith(SpringRunner.class)
+@SpringBootTest
public class ApplicationTests {
@Test
diff --git a/tests/annotation/custom-grant/src/test/java/demo/AuthorizationCodeProviderTests.java b/tests/annotation/custom-grant/src/test/java/demo/AuthorizationCodeProviderTests.java
index 49a38d4ab..34cdef81b 100755
--- a/tests/annotation/custom-grant/src/test/java/demo/AuthorizationCodeProviderTests.java
+++ b/tests/annotation/custom-grant/src/test/java/demo/AuthorizationCodeProviderTests.java
@@ -17,7 +17,6 @@
import static org.junit.Assert.assertTrue;
import org.junit.Test;
-import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.oauth2.client.test.OAuth2ContextConfiguration;
@@ -28,7 +27,6 @@
/**
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes = Application.class)
public class AuthorizationCodeProviderTests extends AbstractAuthorizationCodeProviderTests {
@Test
diff --git a/tests/annotation/custom-grant/src/test/java/demo/ClientCredentialsProviderTests.java b/tests/annotation/custom-grant/src/test/java/demo/ClientCredentialsProviderTests.java
index af8190074..857ff7fa0 100644
--- a/tests/annotation/custom-grant/src/test/java/demo/ClientCredentialsProviderTests.java
+++ b/tests/annotation/custom-grant/src/test/java/demo/ClientCredentialsProviderTests.java
@@ -1,13 +1,10 @@
package demo;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-
import sparklr.common.AbstractClientCredentialsProviderTests;
/**
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes=Application.class)
public class ClientCredentialsProviderTests extends AbstractClientCredentialsProviderTests {
diff --git a/tests/annotation/custom-grant/src/test/java/demo/CustomProviderTests.java b/tests/annotation/custom-grant/src/test/java/demo/CustomProviderTests.java
index 219553795..bd6897227 100644
--- a/tests/annotation/custom-grant/src/test/java/demo/CustomProviderTests.java
+++ b/tests/annotation/custom-grant/src/test/java/demo/CustomProviderTests.java
@@ -1,11 +1,10 @@
package demo;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
import java.util.Map;
import org.junit.Test;
-import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
@@ -17,7 +16,6 @@
/**
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes = Application.class)
public class CustomProviderTests extends AbstractIntegrationTests {
@Test
diff --git a/tests/annotation/custom-grant/src/test/java/demo/ImplicitProviderTests.java b/tests/annotation/custom-grant/src/test/java/demo/ImplicitProviderTests.java
index 92379335a..0945dffce 100644
--- a/tests/annotation/custom-grant/src/test/java/demo/ImplicitProviderTests.java
+++ b/tests/annotation/custom-grant/src/test/java/demo/ImplicitProviderTests.java
@@ -13,8 +13,7 @@
import java.util.concurrent.Future;
import org.junit.Test;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-import org.springframework.boot.test.TestRestTemplate;
+import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.oauth2.client.test.OAuth2ContextConfiguration;
@@ -25,7 +24,6 @@
/**
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes = Application.class)
public class ImplicitProviderTests extends AbstractImplicitProviderTests {
@Test
diff --git a/tests/annotation/custom-grant/src/test/java/demo/ProtectedResourceTests.java b/tests/annotation/custom-grant/src/test/java/demo/ProtectedResourceTests.java
index c752cbe12..302b30f96 100644
--- a/tests/annotation/custom-grant/src/test/java/demo/ProtectedResourceTests.java
+++ b/tests/annotation/custom-grant/src/test/java/demo/ProtectedResourceTests.java
@@ -13,15 +13,12 @@
package demo;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-
import sparklr.common.AbstractProtectedResourceTests;
/**
* @author Dave Syer
*
*/
-@SpringApplicationConfiguration(classes = Application.class)
public class ProtectedResourceTests extends AbstractProtectedResourceTests {
}
diff --git a/tests/annotation/custom-grant/src/test/java/demo/RefreshTokenSupportTests.java b/tests/annotation/custom-grant/src/test/java/demo/RefreshTokenSupportTests.java
index 4ed370eea..417bac867 100644
--- a/tests/annotation/custom-grant/src/test/java/demo/RefreshTokenSupportTests.java
+++ b/tests/annotation/custom-grant/src/test/java/demo/RefreshTokenSupportTests.java
@@ -1,13 +1,10 @@
package demo;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-
import sparklr.common.AbstractRefreshTokenSupportTests;
/**
* @author Ryan Heaton
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes=Application.class)
public class RefreshTokenSupportTests extends AbstractRefreshTokenSupportTests {
}
diff --git a/tests/annotation/custom-grant/src/test/java/demo/ResourceOwnerPasswordProviderTests.java b/tests/annotation/custom-grant/src/test/java/demo/ResourceOwnerPasswordProviderTests.java
index aa5786098..5682e05a6 100644
--- a/tests/annotation/custom-grant/src/test/java/demo/ResourceOwnerPasswordProviderTests.java
+++ b/tests/annotation/custom-grant/src/test/java/demo/ResourceOwnerPasswordProviderTests.java
@@ -1,13 +1,10 @@
package demo;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-
import sparklr.common.AbstractResourceOwnerPasswordProviderTests;
/**
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes=Application.class)
public class ResourceOwnerPasswordProviderTests extends AbstractResourceOwnerPasswordProviderTests {
}
diff --git a/tests/annotation/form/pom.xml b/tests/annotation/form/pom.xml
index 311156648..0170024a6 100644
--- a/tests/annotation/form/pom.xml
+++ b/tests/annotation/form/pom.xml
@@ -10,7 +10,7 @@
org.demo
spring-oauth2-tests-parent
- 2.0.13.BUILD-SNAPSHOT
+ 2.1.1.BUILD-SNAPSHOT
diff --git a/tests/annotation/form/src/main/java/demo/Application.java b/tests/annotation/form/src/main/java/demo/Application.java
index 696029d71..cba6c9f6f 100644
--- a/tests/annotation/form/src/main/java/demo/Application.java
+++ b/tests/annotation/form/src/main/java/demo/Application.java
@@ -2,8 +2,7 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
-import org.springframework.context.annotation.ComponentScan;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
@@ -15,9 +14,7 @@
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
-@Configuration
-@ComponentScan
-@EnableAutoConfiguration
+@SpringBootApplication
@EnableResourceServer
@RestController
public class Application {
diff --git a/tests/annotation/form/src/main/resources/application.yml b/tests/annotation/form/src/main/resources/application.yml
index dbb4d4d3e..57c6bd9cc 100644
--- a/tests/annotation/form/src/main/resources/application.yml
+++ b/tests/annotation/form/src/main/resources/application.yml
@@ -6,6 +6,9 @@ management:
security:
user:
password: password
+ oauth2:
+ resource:
+ filter-order: 3
logging:
level:
org.springframework.security: WARN
diff --git a/tests/annotation/form/src/test/java/demo/ApplicationTests.java b/tests/annotation/form/src/test/java/demo/ApplicationTests.java
index 15eca8da6..34f49b849 100644
--- a/tests/annotation/form/src/test/java/demo/ApplicationTests.java
+++ b/tests/annotation/form/src/test/java/demo/ApplicationTests.java
@@ -2,15 +2,11 @@
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.springframework.boot.test.IntegrationTest;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import org.springframework.test.context.web.WebAppConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
-@RunWith(SpringJUnit4ClassRunner.class)
-@SpringApplicationConfiguration(classes = Application.class)
-@WebAppConfiguration
-@IntegrationTest("server.port=0")
+@RunWith(SpringRunner.class)
+@SpringBootTest
public class ApplicationTests {
@Test
diff --git a/tests/annotation/form/src/test/java/demo/AuthorizationCodeProviderTests.java b/tests/annotation/form/src/test/java/demo/AuthorizationCodeProviderTests.java
index 632098bf1..2ef50fde6 100755
--- a/tests/annotation/form/src/test/java/demo/AuthorizationCodeProviderTests.java
+++ b/tests/annotation/form/src/test/java/demo/AuthorizationCodeProviderTests.java
@@ -12,14 +12,11 @@
*/
package demo;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-
import sparklr.common.AbstractAuthorizationCodeProviderTests;
/**
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes = Application.class)
public class AuthorizationCodeProviderTests extends AbstractAuthorizationCodeProviderTests {
}
diff --git a/tests/annotation/form/src/test/java/demo/ClientCredentialsProviderTests.java b/tests/annotation/form/src/test/java/demo/ClientCredentialsProviderTests.java
index 3d9ccf4f6..d70b43c90 100644
--- a/tests/annotation/form/src/test/java/demo/ClientCredentialsProviderTests.java
+++ b/tests/annotation/form/src/test/java/demo/ClientCredentialsProviderTests.java
@@ -8,7 +8,6 @@
import java.io.IOException;
import org.junit.Test;
-import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.ClientHttpResponse;
@@ -24,7 +23,6 @@
/**
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes=Application.class)
public class ClientCredentialsProviderTests extends AbstractClientCredentialsProviderTests {
private HttpHeaders responseHeaders;
diff --git a/tests/annotation/form/src/test/java/demo/ImplicitProviderTests.java b/tests/annotation/form/src/test/java/demo/ImplicitProviderTests.java
index 7a8958187..0e34ccc7d 100644
--- a/tests/annotation/form/src/test/java/demo/ImplicitProviderTests.java
+++ b/tests/annotation/form/src/test/java/demo/ImplicitProviderTests.java
@@ -1,13 +1,10 @@
package demo;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-
import sparklr.common.AbstractImplicitProviderTests;
/**
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes=Application.class)
public class ImplicitProviderTests extends AbstractImplicitProviderTests {
}
diff --git a/tests/annotation/form/src/test/java/demo/ProtectedResourceTests.java b/tests/annotation/form/src/test/java/demo/ProtectedResourceTests.java
index c752cbe12..302b30f96 100644
--- a/tests/annotation/form/src/test/java/demo/ProtectedResourceTests.java
+++ b/tests/annotation/form/src/test/java/demo/ProtectedResourceTests.java
@@ -13,15 +13,12 @@
package demo;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-
import sparklr.common.AbstractProtectedResourceTests;
/**
* @author Dave Syer
*
*/
-@SpringApplicationConfiguration(classes = Application.class)
public class ProtectedResourceTests extends AbstractProtectedResourceTests {
}
diff --git a/tests/annotation/form/src/test/java/demo/RefreshTokenSupportTests.java b/tests/annotation/form/src/test/java/demo/RefreshTokenSupportTests.java
index 4ed370eea..417bac867 100644
--- a/tests/annotation/form/src/test/java/demo/RefreshTokenSupportTests.java
+++ b/tests/annotation/form/src/test/java/demo/RefreshTokenSupportTests.java
@@ -1,13 +1,10 @@
package demo;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-
import sparklr.common.AbstractRefreshTokenSupportTests;
/**
* @author Ryan Heaton
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes=Application.class)
public class RefreshTokenSupportTests extends AbstractRefreshTokenSupportTests {
}
diff --git a/tests/annotation/form/src/test/java/demo/ResourceOwnerPasswordProviderTests.java b/tests/annotation/form/src/test/java/demo/ResourceOwnerPasswordProviderTests.java
index 6eaa554eb..7fe135878 100644
--- a/tests/annotation/form/src/test/java/demo/ResourceOwnerPasswordProviderTests.java
+++ b/tests/annotation/form/src/test/java/demo/ResourceOwnerPasswordProviderTests.java
@@ -1,6 +1,5 @@
package demo;
-import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.security.oauth2.client.resource.BaseOAuth2ProtectedResourceDetails;
import org.springframework.security.oauth2.client.test.BeforeOAuth2Context;
import org.springframework.security.oauth2.common.AuthenticationScheme;
@@ -10,7 +9,6 @@
/**
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes = Application.class)
public class ResourceOwnerPasswordProviderTests extends
AbstractResourceOwnerPasswordProviderTests {
diff --git a/tests/annotation/jaxb/pom.xml b/tests/annotation/jaxb/pom.xml
index 05fc8f4cd..6b76b5c08 100644
--- a/tests/annotation/jaxb/pom.xml
+++ b/tests/annotation/jaxb/pom.xml
@@ -10,7 +10,7 @@
org.demo
spring-oauth2-tests-parent
- 2.0.13.BUILD-SNAPSHOT
+ 2.1.1.BUILD-SNAPSHOT
diff --git a/tests/annotation/jaxb/src/main/java/demo/Application.java b/tests/annotation/jaxb/src/main/java/demo/Application.java
index 956c80ffd..a9ec20e09 100644
--- a/tests/annotation/jaxb/src/main/java/demo/Application.java
+++ b/tests/annotation/jaxb/src/main/java/demo/Application.java
@@ -5,8 +5,7 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
-import org.springframework.context.annotation.ComponentScan;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.security.authentication.AuthenticationManager;
@@ -28,9 +27,7 @@
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
-@Configuration
-@ComponentScan
-@EnableAutoConfiguration
+@SpringBootApplication
@EnableResourceServer
@RestController
public class Application extends WebMvcConfigurerAdapter {
diff --git a/tests/annotation/jaxb/src/main/resources/application.yml b/tests/annotation/jaxb/src/main/resources/application.yml
index a9c0149f0..c88891b00 100644
--- a/tests/annotation/jaxb/src/main/resources/application.yml
+++ b/tests/annotation/jaxb/src/main/resources/application.yml
@@ -6,3 +6,6 @@ management:
security:
user:
password: password
+ oauth2:
+ resource:
+ filter-order: 3
diff --git a/tests/annotation/jaxb/src/test/java/demo/ApplicationTests.java b/tests/annotation/jaxb/src/test/java/demo/ApplicationTests.java
index 15eca8da6..34f49b849 100644
--- a/tests/annotation/jaxb/src/test/java/demo/ApplicationTests.java
+++ b/tests/annotation/jaxb/src/test/java/demo/ApplicationTests.java
@@ -2,15 +2,11 @@
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.springframework.boot.test.IntegrationTest;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import org.springframework.test.context.web.WebAppConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
-@RunWith(SpringJUnit4ClassRunner.class)
-@SpringApplicationConfiguration(classes = Application.class)
-@WebAppConfiguration
-@IntegrationTest("server.port=0")
+@RunWith(SpringRunner.class)
+@SpringBootTest
public class ApplicationTests {
@Test
diff --git a/tests/annotation/jaxb/src/test/java/demo/AuthorizationCodeProviderTests.java b/tests/annotation/jaxb/src/test/java/demo/AuthorizationCodeProviderTests.java
index 7d8889a6c..0333fa789 100755
--- a/tests/annotation/jaxb/src/test/java/demo/AuthorizationCodeProviderTests.java
+++ b/tests/annotation/jaxb/src/test/java/demo/AuthorizationCodeProviderTests.java
@@ -18,7 +18,6 @@
import java.util.Collection;
import org.junit.Test;
-import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageConverter;
@@ -28,7 +27,6 @@
/**
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes = Application.class)
public class AuthorizationCodeProviderTests extends AbstractAuthorizationCodeProviderTests {
@Test
diff --git a/tests/annotation/jaxb/src/test/java/demo/ClientCredentialsProviderTests.java b/tests/annotation/jaxb/src/test/java/demo/ClientCredentialsProviderTests.java
index ef9ade0cd..b24e666c8 100644
--- a/tests/annotation/jaxb/src/test/java/demo/ClientCredentialsProviderTests.java
+++ b/tests/annotation/jaxb/src/test/java/demo/ClientCredentialsProviderTests.java
@@ -3,7 +3,6 @@
import java.util.Collection;
import java.util.List;
-import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.converter.HttpMessageConverter;
@@ -12,7 +11,6 @@
/**
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes=Application.class)
public class ClientCredentialsProviderTests extends AbstractClientCredentialsProviderTests {
@Override
diff --git a/tests/annotation/jaxb/src/test/java/demo/ImplicitProviderTests.java b/tests/annotation/jaxb/src/test/java/demo/ImplicitProviderTests.java
index 874e9ca09..d5bbfd381 100644
--- a/tests/annotation/jaxb/src/test/java/demo/ImplicitProviderTests.java
+++ b/tests/annotation/jaxb/src/test/java/demo/ImplicitProviderTests.java
@@ -13,8 +13,7 @@
import java.util.concurrent.Future;
import org.junit.Test;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-import org.springframework.boot.test.TestRestTemplate;
+import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageConverter;
@@ -26,7 +25,6 @@
/**
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes = Application.class)
public class ImplicitProviderTests extends AbstractImplicitProviderTests {
@Test
diff --git a/tests/annotation/jaxb/src/test/java/demo/ProtectedResourceTests.java b/tests/annotation/jaxb/src/test/java/demo/ProtectedResourceTests.java
index d47fb4893..0a539c5f4 100644
--- a/tests/annotation/jaxb/src/test/java/demo/ProtectedResourceTests.java
+++ b/tests/annotation/jaxb/src/test/java/demo/ProtectedResourceTests.java
@@ -15,7 +15,6 @@
import java.util.Collection;
-import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.http.converter.HttpMessageConverter;
import sparklr.common.AbstractProtectedResourceTests;
@@ -24,7 +23,6 @@
* @author Dave Syer
*
*/
-@SpringApplicationConfiguration(classes = Application.class)
public class ProtectedResourceTests extends AbstractProtectedResourceTests {
@Override
diff --git a/tests/annotation/jaxb/src/test/java/demo/RefreshTokenSupportTests.java b/tests/annotation/jaxb/src/test/java/demo/RefreshTokenSupportTests.java
index adcaa1326..06804a151 100644
--- a/tests/annotation/jaxb/src/test/java/demo/RefreshTokenSupportTests.java
+++ b/tests/annotation/jaxb/src/test/java/demo/RefreshTokenSupportTests.java
@@ -2,7 +2,6 @@
import java.util.Collection;
-import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.http.converter.HttpMessageConverter;
import sparklr.common.AbstractRefreshTokenSupportTests;
@@ -11,7 +10,6 @@
* @author Ryan Heaton
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes=Application.class)
public class RefreshTokenSupportTests extends AbstractRefreshTokenSupportTests {
@Override
diff --git a/tests/annotation/jaxb/src/test/java/demo/ResourceOwnerPasswordProviderTests.java b/tests/annotation/jaxb/src/test/java/demo/ResourceOwnerPasswordProviderTests.java
index c41de197c..c69f87d8a 100644
--- a/tests/annotation/jaxb/src/test/java/demo/ResourceOwnerPasswordProviderTests.java
+++ b/tests/annotation/jaxb/src/test/java/demo/ResourceOwnerPasswordProviderTests.java
@@ -2,7 +2,6 @@
import java.util.Collection;
-import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.http.converter.HttpMessageConverter;
import sparklr.common.AbstractResourceOwnerPasswordProviderTests;
@@ -10,7 +9,6 @@
/**
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes=Application.class)
public class ResourceOwnerPasswordProviderTests extends AbstractResourceOwnerPasswordProviderTests {
@Override
diff --git a/tests/annotation/jdbc/pom.xml b/tests/annotation/jdbc/pom.xml
index b38274a78..2035871b8 100644
--- a/tests/annotation/jdbc/pom.xml
+++ b/tests/annotation/jdbc/pom.xml
@@ -10,7 +10,7 @@
org.demo
spring-oauth2-tests-parent
- 2.0.13.BUILD-SNAPSHOT
+ 2.1.1.BUILD-SNAPSHOT
diff --git a/tests/annotation/jdbc/src/main/java/demo/Application.java b/tests/annotation/jdbc/src/main/java/demo/Application.java
index 36f243d80..300e4f250 100644
--- a/tests/annotation/jdbc/src/main/java/demo/Application.java
+++ b/tests/annotation/jdbc/src/main/java/demo/Application.java
@@ -129,7 +129,7 @@ public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
public void init(AuthenticationManagerBuilder auth) throws Exception {
// @formatter:off
auth.jdbcAuthentication().dataSource(dataSource).withUser("dave")
- .password("secret").roles("USER");
+ .password("secret").roles("USER", "ACTUATOR");
// @formatter:on
}
diff --git a/tests/annotation/jdbc/src/main/resources/application.yml b/tests/annotation/jdbc/src/main/resources/application.yml
index da08708a2..d83b7e17a 100644
--- a/tests/annotation/jdbc/src/main/resources/application.yml
+++ b/tests/annotation/jdbc/src/main/resources/application.yml
@@ -3,6 +3,10 @@ spring:
name: jdbc
management:
context_path: /admin
+security:
+ oauth2:
+ resource:
+ filter-order: 3
logging:
level:
# org.springframework.security: DEBUG
diff --git a/tests/annotation/jdbc/src/test/java/demo/ApplicationTests.java b/tests/annotation/jdbc/src/test/java/demo/ApplicationTests.java
index ac31a7866..20748d419 100644
--- a/tests/annotation/jdbc/src/test/java/demo/ApplicationTests.java
+++ b/tests/annotation/jdbc/src/test/java/demo/ApplicationTests.java
@@ -3,22 +3,17 @@
import static org.junit.Assert.assertTrue;
import org.junit.Test;
-import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.IntegrationTest;
-import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import org.springframework.test.context.web.WebAppConfiguration;
+import org.springframework.test.context.ContextConfiguration;
-@RunWith(SpringJUnit4ClassRunner.class)
-@SpringApplicationConfiguration(classes = Application.class)
-@WebAppConfiguration
-@IntegrationTest("server.port=0")
-public class ApplicationTests {
+import sparklr.common.AbstractIntegrationTests;
+
+@ContextConfiguration(classes=Application.class)
+public class ApplicationTests extends AbstractIntegrationTests {
@Autowired
private TokenStore tokenStore;
diff --git a/tests/annotation/jdbc/src/test/java/demo/AuthorizationCodeProviderTests.java b/tests/annotation/jdbc/src/test/java/demo/AuthorizationCodeProviderTests.java
index 40787edad..5882b7cd3 100755
--- a/tests/annotation/jdbc/src/test/java/demo/AuthorizationCodeProviderTests.java
+++ b/tests/annotation/jdbc/src/test/java/demo/AuthorizationCodeProviderTests.java
@@ -15,14 +15,14 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
-import org.springframework.boot.test.SpringApplicationConfiguration;
+import org.springframework.test.context.ContextConfiguration;
import sparklr.common.AbstractAuthorizationCodeProviderTests;
/**
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes = Application.class)
+@ContextConfiguration(classes=Application.class)
public class AuthorizationCodeProviderTests extends AbstractAuthorizationCodeProviderTests {
protected String getPassword() {
diff --git a/tests/annotation/jdbc/src/test/java/demo/ClientCredentialsProviderTests.java b/tests/annotation/jdbc/src/test/java/demo/ClientCredentialsProviderTests.java
index af8190074..e23fe4f49 100644
--- a/tests/annotation/jdbc/src/test/java/demo/ClientCredentialsProviderTests.java
+++ b/tests/annotation/jdbc/src/test/java/demo/ClientCredentialsProviderTests.java
@@ -1,13 +1,13 @@
package demo;
-import org.springframework.boot.test.SpringApplicationConfiguration;
+import org.springframework.test.context.ContextConfiguration;
import sparklr.common.AbstractClientCredentialsProviderTests;
/**
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes=Application.class)
+@ContextConfiguration(classes=Application.class)
public class ClientCredentialsProviderTests extends AbstractClientCredentialsProviderTests {
diff --git a/tests/annotation/jdbc/src/test/java/demo/ImplicitProviderTests.java b/tests/annotation/jdbc/src/test/java/demo/ImplicitProviderTests.java
index 89b5a1ef8..225c53741 100644
--- a/tests/annotation/jdbc/src/test/java/demo/ImplicitProviderTests.java
+++ b/tests/annotation/jdbc/src/test/java/demo/ImplicitProviderTests.java
@@ -1,13 +1,13 @@
package demo;
-import org.springframework.boot.test.SpringApplicationConfiguration;
+import org.springframework.test.context.ContextConfiguration;
import sparklr.common.AbstractImplicitProviderTests;
/**
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes=Application.class)
+@ContextConfiguration(classes=Application.class)
public class ImplicitProviderTests extends AbstractImplicitProviderTests {
protected String getPassword() {
diff --git a/tests/annotation/jdbc/src/test/java/demo/ProtectedResourceTests.java b/tests/annotation/jdbc/src/test/java/demo/ProtectedResourceTests.java
index c752cbe12..0e2acc8d9 100644
--- a/tests/annotation/jdbc/src/test/java/demo/ProtectedResourceTests.java
+++ b/tests/annotation/jdbc/src/test/java/demo/ProtectedResourceTests.java
@@ -13,7 +13,7 @@
package demo;
-import org.springframework.boot.test.SpringApplicationConfiguration;
+import org.springframework.test.context.ContextConfiguration;
import sparklr.common.AbstractProtectedResourceTests;
@@ -21,7 +21,7 @@
* @author Dave Syer
*
*/
-@SpringApplicationConfiguration(classes = Application.class)
+@ContextConfiguration(classes=Application.class)
public class ProtectedResourceTests extends AbstractProtectedResourceTests {
}
diff --git a/tests/annotation/jdbc/src/test/java/demo/RefreshTokenSupportTests.java b/tests/annotation/jdbc/src/test/java/demo/RefreshTokenSupportTests.java
index 299e66005..9d2a59ca6 100644
--- a/tests/annotation/jdbc/src/test/java/demo/RefreshTokenSupportTests.java
+++ b/tests/annotation/jdbc/src/test/java/demo/RefreshTokenSupportTests.java
@@ -1,6 +1,6 @@
package demo;
-import org.springframework.boot.test.SpringApplicationConfiguration;
+import org.springframework.test.context.ContextConfiguration;
import sparklr.common.AbstractRefreshTokenSupportTests;
@@ -8,7 +8,7 @@
* @author Ryan Heaton
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes=Application.class)
+@ContextConfiguration(classes=Application.class)
public class RefreshTokenSupportTests extends AbstractRefreshTokenSupportTests {
protected String getPassword() {
return "secret";
diff --git a/tests/annotation/jdbc/src/test/java/demo/ResourceOwnerPasswordProviderTests.java b/tests/annotation/jdbc/src/test/java/demo/ResourceOwnerPasswordProviderTests.java
index 65c784f57..408aeae50 100644
--- a/tests/annotation/jdbc/src/test/java/demo/ResourceOwnerPasswordProviderTests.java
+++ b/tests/annotation/jdbc/src/test/java/demo/ResourceOwnerPasswordProviderTests.java
@@ -4,16 +4,16 @@
import static org.junit.Assert.assertTrue;
import org.junit.Test;
-import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.http.HttpStatus;
import org.springframework.security.oauth2.client.test.OAuth2ContextConfiguration;
+import org.springframework.test.context.ContextConfiguration;
import sparklr.common.AbstractResourceOwnerPasswordProviderTests;
/**
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes = Application.class)
+@ContextConfiguration(classes=Application.class)
public class ResourceOwnerPasswordProviderTests extends AbstractResourceOwnerPasswordProviderTests {
protected String getPassword() {
diff --git a/tests/annotation/jpa/pom.xml b/tests/annotation/jpa/pom.xml
index b82319fc0..e973072a1 100644
--- a/tests/annotation/jpa/pom.xml
+++ b/tests/annotation/jpa/pom.xml
@@ -10,7 +10,7 @@
org.demo
spring-oauth2-tests-parent
- 2.0.13.BUILD-SNAPSHOT
+ 2.1.1.BUILD-SNAPSHOT
diff --git a/tests/annotation/jpa/src/main/java/demo/Application.java b/tests/annotation/jpa/src/main/java/demo/Application.java
index 5cb7f67a1..20b5aecbc 100644
--- a/tests/annotation/jpa/src/main/java/demo/Application.java
+++ b/tests/annotation/jpa/src/main/java/demo/Application.java
@@ -95,7 +95,7 @@ public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
@Autowired
public void authenticationManager(AuthenticationManagerBuilder builder, UserRepository repository) throws Exception {
if (repository.count()==0) {
- repository.save(new User("user", "password", Arrays.asList(new Role("USER"))));
+ repository.save(new User("user", "password", Arrays.asList(new Role("USER"), new Role("ACTUATOR"))));
}
builder.userDetailsService(userDetailsService(repository));
}
diff --git a/tests/annotation/jpa/src/main/resources/application.yml b/tests/annotation/jpa/src/main/resources/application.yml
index faea2bd5a..85e3c2c52 100644
--- a/tests/annotation/jpa/src/main/resources/application.yml
+++ b/tests/annotation/jpa/src/main/resources/application.yml
@@ -6,6 +6,9 @@ management:
security:
user:
password: password
+ oauth2:
+ resource:
+ filter-order: 3
logging:
level:
# org.springframework.security: DEBUG
diff --git a/tests/annotation/jpa/src/test/java/demo/ApplicationTests.java b/tests/annotation/jpa/src/test/java/demo/ApplicationTests.java
index 15eca8da6..34f49b849 100644
--- a/tests/annotation/jpa/src/test/java/demo/ApplicationTests.java
+++ b/tests/annotation/jpa/src/test/java/demo/ApplicationTests.java
@@ -2,15 +2,11 @@
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.springframework.boot.test.IntegrationTest;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import org.springframework.test.context.web.WebAppConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
-@RunWith(SpringJUnit4ClassRunner.class)
-@SpringApplicationConfiguration(classes = Application.class)
-@WebAppConfiguration
-@IntegrationTest("server.port=0")
+@RunWith(SpringRunner.class)
+@SpringBootTest
public class ApplicationTests {
@Test
diff --git a/tests/annotation/jpa/src/test/java/demo/AuthorizationCodeProviderCookieTests.java b/tests/annotation/jpa/src/test/java/demo/AuthorizationCodeProviderCookieTests.java
index 7b614e004..e9083e3f3 100644
--- a/tests/annotation/jpa/src/test/java/demo/AuthorizationCodeProviderCookieTests.java
+++ b/tests/annotation/jpa/src/test/java/demo/AuthorizationCodeProviderCookieTests.java
@@ -16,7 +16,6 @@
import static org.junit.Assert.assertNotNull;
import org.junit.Test;
-import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.security.oauth2.client.test.OAuth2ContextConfiguration;
@@ -27,7 +26,6 @@
/**
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes = Application.class)
public class AuthorizationCodeProviderCookieTests extends AbstractEmptyAuthorizationCodeProviderTests {
@Test
diff --git a/tests/annotation/jpa/src/test/java/demo/AuthorizationCodeProviderTests.java b/tests/annotation/jpa/src/test/java/demo/AuthorizationCodeProviderTests.java
index 49a38d4ab..34cdef81b 100755
--- a/tests/annotation/jpa/src/test/java/demo/AuthorizationCodeProviderTests.java
+++ b/tests/annotation/jpa/src/test/java/demo/AuthorizationCodeProviderTests.java
@@ -17,7 +17,6 @@
import static org.junit.Assert.assertTrue;
import org.junit.Test;
-import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.oauth2.client.test.OAuth2ContextConfiguration;
@@ -28,7 +27,6 @@
/**
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes = Application.class)
public class AuthorizationCodeProviderTests extends AbstractAuthorizationCodeProviderTests {
@Test
diff --git a/tests/annotation/jpa/src/test/java/demo/ClientCredentialsProviderTests.java b/tests/annotation/jpa/src/test/java/demo/ClientCredentialsProviderTests.java
index af8190074..857ff7fa0 100644
--- a/tests/annotation/jpa/src/test/java/demo/ClientCredentialsProviderTests.java
+++ b/tests/annotation/jpa/src/test/java/demo/ClientCredentialsProviderTests.java
@@ -1,13 +1,10 @@
package demo;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-
import sparklr.common.AbstractClientCredentialsProviderTests;
/**
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes=Application.class)
public class ClientCredentialsProviderTests extends AbstractClientCredentialsProviderTests {
diff --git a/tests/annotation/jpa/src/test/java/demo/ImplicitProviderTests.java b/tests/annotation/jpa/src/test/java/demo/ImplicitProviderTests.java
index 06ebe766b..ef7c254ce 100644
--- a/tests/annotation/jpa/src/test/java/demo/ImplicitProviderTests.java
+++ b/tests/annotation/jpa/src/test/java/demo/ImplicitProviderTests.java
@@ -14,8 +14,7 @@
import org.junit.BeforeClass;
import org.junit.Test;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-import org.springframework.boot.test.TestRestTemplate;
+import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.oauth2.client.test.OAuth2ContextConfiguration;
@@ -26,7 +25,6 @@
/**
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes = Application.class)
public class ImplicitProviderTests extends AbstractImplicitProviderTests {
@BeforeClass
diff --git a/tests/annotation/jpa/src/test/java/demo/ProtectedResourceTests.java b/tests/annotation/jpa/src/test/java/demo/ProtectedResourceTests.java
index c752cbe12..302b30f96 100644
--- a/tests/annotation/jpa/src/test/java/demo/ProtectedResourceTests.java
+++ b/tests/annotation/jpa/src/test/java/demo/ProtectedResourceTests.java
@@ -13,15 +13,12 @@
package demo;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-
import sparklr.common.AbstractProtectedResourceTests;
/**
* @author Dave Syer
*
*/
-@SpringApplicationConfiguration(classes = Application.class)
public class ProtectedResourceTests extends AbstractProtectedResourceTests {
}
diff --git a/tests/annotation/jpa/src/test/java/demo/RefreshTokenSupportTests.java b/tests/annotation/jpa/src/test/java/demo/RefreshTokenSupportTests.java
index 4ed370eea..417bac867 100644
--- a/tests/annotation/jpa/src/test/java/demo/RefreshTokenSupportTests.java
+++ b/tests/annotation/jpa/src/test/java/demo/RefreshTokenSupportTests.java
@@ -1,13 +1,10 @@
package demo;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-
import sparklr.common.AbstractRefreshTokenSupportTests;
/**
* @author Ryan Heaton
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes=Application.class)
public class RefreshTokenSupportTests extends AbstractRefreshTokenSupportTests {
}
diff --git a/tests/annotation/jpa/src/test/java/demo/ResourceOwnerPasswordProviderTests.java b/tests/annotation/jpa/src/test/java/demo/ResourceOwnerPasswordProviderTests.java
index 28a8e9f84..31a0f75b8 100644
--- a/tests/annotation/jpa/src/test/java/demo/ResourceOwnerPasswordProviderTests.java
+++ b/tests/annotation/jpa/src/test/java/demo/ResourceOwnerPasswordProviderTests.java
@@ -3,8 +3,7 @@
import static org.junit.Assert.assertEquals;
import org.junit.Test;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-import org.springframework.boot.test.TestRestTemplate;
+import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.oauth2.client.test.OAuth2ContextConfiguration;
@@ -14,7 +13,6 @@
/**
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes=Application.class)
public class ResourceOwnerPasswordProviderTests extends AbstractResourceOwnerPasswordProviderTests {
@Test
diff --git a/tests/annotation/jwt/pom.xml b/tests/annotation/jwt/pom.xml
index 6d92b9026..46c3a4609 100644
--- a/tests/annotation/jwt/pom.xml
+++ b/tests/annotation/jwt/pom.xml
@@ -10,7 +10,7 @@
org.demo
spring-oauth2-tests-parent
- 2.0.13.BUILD-SNAPSHOT
+ 2.1.1.BUILD-SNAPSHOT
diff --git a/tests/annotation/jwt/src/main/java/demo/Application.java b/tests/annotation/jwt/src/main/java/demo/Application.java
index 5d5c71d5f..0aebd4b1f 100644
--- a/tests/annotation/jwt/src/main/java/demo/Application.java
+++ b/tests/annotation/jwt/src/main/java/demo/Application.java
@@ -2,9 +2,8 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
@@ -17,9 +16,7 @@
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
-@Configuration
-@ComponentScan
-@EnableAutoConfiguration
+@SpringBootApplication
@EnableResourceServer
@RestController
public class Application {
diff --git a/tests/annotation/jwt/src/main/resources/application.yml b/tests/annotation/jwt/src/main/resources/application.yml
index ccf06f8ba..8f7a77341 100644
--- a/tests/annotation/jwt/src/main/resources/application.yml
+++ b/tests/annotation/jwt/src/main/resources/application.yml
@@ -6,6 +6,9 @@ management:
security:
user:
password: password
+ oauth2:
+ resource:
+ filter-order: 3
logging:
level:
# org.springframework.security: DEBUG
\ No newline at end of file
diff --git a/tests/annotation/jwt/src/test/java/demo/ApplicationTests.java b/tests/annotation/jwt/src/test/java/demo/ApplicationTests.java
index 82a5ffee6..1bb5192c6 100644
--- a/tests/annotation/jwt/src/test/java/demo/ApplicationTests.java
+++ b/tests/annotation/jwt/src/test/java/demo/ApplicationTests.java
@@ -6,30 +6,25 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.boot.test.IntegrationTest;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-import org.springframework.boot.test.TestRestTemplate;
+import org.springframework.boot.context.embedded.LocalServerPort;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
+import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.HttpStatus;
-import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
+import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import org.springframework.test.context.web.WebAppConfiguration;
+import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.util.ReflectionTestUtils;
-@RunWith(SpringJUnit4ClassRunner.class)
-@SpringApplicationConfiguration(classes = Application.class)
-@WebAppConfiguration
-@IntegrationTest("server.port=0")
+@RunWith(SpringRunner.class)
+@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)
public class ApplicationTests {
- @Value("${local.server.port}")
+ @LocalServerPort
private int port;
@Autowired
- @Qualifier("defaultAuthorizationServerTokenServices")
- private DefaultTokenServices tokenServices;
+ private AuthorizationServerTokenServices tokenServices;
@Test
public void tokenStoreIsJwt() {
diff --git a/tests/annotation/jwt/src/test/java/demo/AuthorizationCodeProviderTests.java b/tests/annotation/jwt/src/test/java/demo/AuthorizationCodeProviderTests.java
index 632098bf1..2ef50fde6 100755
--- a/tests/annotation/jwt/src/test/java/demo/AuthorizationCodeProviderTests.java
+++ b/tests/annotation/jwt/src/test/java/demo/AuthorizationCodeProviderTests.java
@@ -12,14 +12,11 @@
*/
package demo;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-
import sparklr.common.AbstractAuthorizationCodeProviderTests;
/**
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes = Application.class)
public class AuthorizationCodeProviderTests extends AbstractAuthorizationCodeProviderTests {
}
diff --git a/tests/annotation/jwt/src/test/java/demo/ClientCredentialsProviderTests.java b/tests/annotation/jwt/src/test/java/demo/ClientCredentialsProviderTests.java
index f26763279..26ee5e7cf 100644
--- a/tests/annotation/jwt/src/test/java/demo/ClientCredentialsProviderTests.java
+++ b/tests/annotation/jwt/src/test/java/demo/ClientCredentialsProviderTests.java
@@ -6,8 +6,7 @@
import java.util.Map;
import org.junit.Test;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-import org.springframework.boot.test.TestRestTemplate;
+import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
@@ -23,7 +22,6 @@
/**
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes = Application.class)
public class ClientCredentialsProviderTests extends AbstractClientCredentialsProviderTests {
/**
diff --git a/tests/annotation/jwt/src/test/java/demo/ImplicitProviderTests.java b/tests/annotation/jwt/src/test/java/demo/ImplicitProviderTests.java
index 7a8958187..0e34ccc7d 100644
--- a/tests/annotation/jwt/src/test/java/demo/ImplicitProviderTests.java
+++ b/tests/annotation/jwt/src/test/java/demo/ImplicitProviderTests.java
@@ -1,13 +1,10 @@
package demo;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-
import sparklr.common.AbstractImplicitProviderTests;
/**
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes=Application.class)
public class ImplicitProviderTests extends AbstractImplicitProviderTests {
}
diff --git a/tests/annotation/jwt/src/test/java/demo/ProtectedResourceTests.java b/tests/annotation/jwt/src/test/java/demo/ProtectedResourceTests.java
index c752cbe12..302b30f96 100644
--- a/tests/annotation/jwt/src/test/java/demo/ProtectedResourceTests.java
+++ b/tests/annotation/jwt/src/test/java/demo/ProtectedResourceTests.java
@@ -13,15 +13,12 @@
package demo;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-
import sparklr.common.AbstractProtectedResourceTests;
/**
* @author Dave Syer
*
*/
-@SpringApplicationConfiguration(classes = Application.class)
public class ProtectedResourceTests extends AbstractProtectedResourceTests {
}
diff --git a/tests/annotation/jwt/src/test/java/demo/RefreshTokenSupportTests.java b/tests/annotation/jwt/src/test/java/demo/RefreshTokenSupportTests.java
index 295fbdabf..28349045f 100644
--- a/tests/annotation/jwt/src/test/java/demo/RefreshTokenSupportTests.java
+++ b/tests/annotation/jwt/src/test/java/demo/RefreshTokenSupportTests.java
@@ -3,11 +3,9 @@
import static org.junit.Assert.assertEquals;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.http.HttpStatus;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
-import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
+import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.test.util.ReflectionTestUtils;
@@ -17,12 +15,10 @@
* @author Ryan Heaton
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes=Application.class)
public class RefreshTokenSupportTests extends AbstractRefreshTokenSupportTests {
@Autowired
- @Qualifier("defaultAuthorizationServerTokenServices")
- private DefaultTokenServices services;
+ private AuthorizationServerTokenServices services;
protected void verifyAccessTokens(OAuth2AccessToken oldAccessToken, OAuth2AccessToken newAccessToken) {
// make sure the new access token can be used.
diff --git a/tests/annotation/jwt/src/test/java/demo/ResourceOwnerPasswordProviderTests.java b/tests/annotation/jwt/src/test/java/demo/ResourceOwnerPasswordProviderTests.java
index d233098a2..4625d154e 100644
--- a/tests/annotation/jwt/src/test/java/demo/ResourceOwnerPasswordProviderTests.java
+++ b/tests/annotation/jwt/src/test/java/demo/ResourceOwnerPasswordProviderTests.java
@@ -6,8 +6,7 @@
import java.util.Map;
import org.junit.Test;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-import org.springframework.boot.test.TestRestTemplate;
+import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
@@ -24,7 +23,6 @@
/**
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes=Application.class)
public class ResourceOwnerPasswordProviderTests extends AbstractResourceOwnerPasswordProviderTests {
@Test
diff --git a/tests/annotation/mappings/pom.xml b/tests/annotation/mappings/pom.xml
index 8346ed914..eff643328 100644
--- a/tests/annotation/mappings/pom.xml
+++ b/tests/annotation/mappings/pom.xml
@@ -10,7 +10,7 @@
org.demo
spring-oauth2-tests-parent
- 2.0.13.BUILD-SNAPSHOT
+ 2.1.1.BUILD-SNAPSHOT
diff --git a/tests/annotation/mappings/src/main/resources/application.yml b/tests/annotation/mappings/src/main/resources/application.yml
index 3b09181d7..5f71e88df 100644
--- a/tests/annotation/mappings/src/main/resources/application.yml
+++ b/tests/annotation/mappings/src/main/resources/application.yml
@@ -6,6 +6,9 @@ management:
security:
user:
password: password
+ oauth2:
+ resource:
+ filter-order: 3
logging:
level:
# org.springframework.security: DEBUG
diff --git a/tests/annotation/mappings/src/test/java/demo/ApplicationTests.java b/tests/annotation/mappings/src/test/java/demo/ApplicationTests.java
index 15eca8da6..34f49b849 100644
--- a/tests/annotation/mappings/src/test/java/demo/ApplicationTests.java
+++ b/tests/annotation/mappings/src/test/java/demo/ApplicationTests.java
@@ -2,15 +2,11 @@
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.springframework.boot.test.IntegrationTest;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import org.springframework.test.context.web.WebAppConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
-@RunWith(SpringJUnit4ClassRunner.class)
-@SpringApplicationConfiguration(classes = Application.class)
-@WebAppConfiguration
-@IntegrationTest("server.port=0")
+@RunWith(SpringRunner.class)
+@SpringBootTest
public class ApplicationTests {
@Test
diff --git a/tests/annotation/mappings/src/test/java/demo/AuthorizationCodeProviderTests.java b/tests/annotation/mappings/src/test/java/demo/AuthorizationCodeProviderTests.java
index 04f4e3c31..5fba9cfe0 100755
--- a/tests/annotation/mappings/src/test/java/demo/AuthorizationCodeProviderTests.java
+++ b/tests/annotation/mappings/src/test/java/demo/AuthorizationCodeProviderTests.java
@@ -19,7 +19,6 @@
import java.util.Arrays;
import org.junit.Test;
-import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.security.oauth2.client.test.OAuth2ContextConfiguration;
import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails;
import org.springframework.security.oauth2.common.exceptions.InsufficientScopeException;
@@ -29,7 +28,6 @@
/**
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes = Application.class)
public class AuthorizationCodeProviderTests extends AbstractAuthorizationCodeProviderTests {
@Test
diff --git a/tests/annotation/mappings/src/test/java/demo/ClientCredentialsProviderTests.java b/tests/annotation/mappings/src/test/java/demo/ClientCredentialsProviderTests.java
index 8c5a6ceac..3765b268e 100644
--- a/tests/annotation/mappings/src/test/java/demo/ClientCredentialsProviderTests.java
+++ b/tests/annotation/mappings/src/test/java/demo/ClientCredentialsProviderTests.java
@@ -6,8 +6,7 @@
import java.util.Map;
import org.junit.Test;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-import org.springframework.boot.test.TestRestTemplate;
+import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
@@ -23,7 +22,6 @@
/**
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes=Application.class)
public class ClientCredentialsProviderTests extends AbstractClientCredentialsProviderTests {
/**
diff --git a/tests/annotation/mappings/src/test/java/demo/ImplicitProviderTests.java b/tests/annotation/mappings/src/test/java/demo/ImplicitProviderTests.java
index 7a8958187..0e34ccc7d 100644
--- a/tests/annotation/mappings/src/test/java/demo/ImplicitProviderTests.java
+++ b/tests/annotation/mappings/src/test/java/demo/ImplicitProviderTests.java
@@ -1,13 +1,10 @@
package demo;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-
import sparklr.common.AbstractImplicitProviderTests;
/**
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes=Application.class)
public class ImplicitProviderTests extends AbstractImplicitProviderTests {
}
diff --git a/tests/annotation/mappings/src/test/java/demo/ProtectedResourceTests.java b/tests/annotation/mappings/src/test/java/demo/ProtectedResourceTests.java
index 743d9158b..4f5e357cc 100644
--- a/tests/annotation/mappings/src/test/java/demo/ProtectedResourceTests.java
+++ b/tests/annotation/mappings/src/test/java/demo/ProtectedResourceTests.java
@@ -17,7 +17,6 @@
import static org.junit.Assert.assertTrue;
import org.junit.Test;
-import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
@@ -27,7 +26,6 @@
* @author Dave Syer
*
*/
-@SpringApplicationConfiguration(classes = Application.class)
public class ProtectedResourceTests extends AbstractProtectedResourceTests {
@Test
diff --git a/tests/annotation/mappings/src/test/java/demo/RefreshTokenSupportTests.java b/tests/annotation/mappings/src/test/java/demo/RefreshTokenSupportTests.java
index 4ed370eea..417bac867 100644
--- a/tests/annotation/mappings/src/test/java/demo/RefreshTokenSupportTests.java
+++ b/tests/annotation/mappings/src/test/java/demo/RefreshTokenSupportTests.java
@@ -1,13 +1,10 @@
package demo;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-
import sparklr.common.AbstractRefreshTokenSupportTests;
/**
* @author Ryan Heaton
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes=Application.class)
public class RefreshTokenSupportTests extends AbstractRefreshTokenSupportTests {
}
diff --git a/tests/annotation/mappings/src/test/java/demo/ResourceOwnerPasswordProviderTests.java b/tests/annotation/mappings/src/test/java/demo/ResourceOwnerPasswordProviderTests.java
index aa5786098..5682e05a6 100644
--- a/tests/annotation/mappings/src/test/java/demo/ResourceOwnerPasswordProviderTests.java
+++ b/tests/annotation/mappings/src/test/java/demo/ResourceOwnerPasswordProviderTests.java
@@ -1,13 +1,10 @@
package demo;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-
import sparklr.common.AbstractResourceOwnerPasswordProviderTests;
/**
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes=Application.class)
public class ResourceOwnerPasswordProviderTests extends AbstractResourceOwnerPasswordProviderTests {
}
diff --git a/tests/annotation/mappings/src/test/java/demo/ServletPathClientCredentialsProviderTests.java b/tests/annotation/mappings/src/test/java/demo/ServletPathClientCredentialsProviderTests.java
index e5344a065..967c864ef 100644
--- a/tests/annotation/mappings/src/test/java/demo/ServletPathClientCredentialsProviderTests.java
+++ b/tests/annotation/mappings/src/test/java/demo/ServletPathClientCredentialsProviderTests.java
@@ -5,21 +5,18 @@
import java.util.Map;
import org.junit.Test;
-import org.springframework.boot.test.IntegrationTest;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-import org.springframework.boot.test.TestRestTemplate;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
+import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
-import org.springframework.test.annotation.DirtiesContext;
import sparklr.common.AbstractClientCredentialsProviderTests;
/**
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes=Application.class)
-@IntegrationTest({"server.servlet_path:/server", "server.port=0"})
-@DirtiesContext
+@SpringBootTest(classes=Application.class, properties="server.servlet_path:/server", webEnvironment=WebEnvironment.RANDOM_PORT)
public class ServletPathClientCredentialsProviderTests extends AbstractClientCredentialsProviderTests {
@Test
diff --git a/tests/annotation/multi/pom.xml b/tests/annotation/multi/pom.xml
index e2634b7c1..554119314 100644
--- a/tests/annotation/multi/pom.xml
+++ b/tests/annotation/multi/pom.xml
@@ -9,7 +9,7 @@
org.demo
spring-oauth2-tests-parent
- 2.0.13.BUILD-SNAPSHOT
+ 2.1.1.BUILD-SNAPSHOT
diff --git a/tests/annotation/multi/src/main/java/demo/Application.java b/tests/annotation/multi/src/main/java/demo/Application.java
index a740fd5d6..e7e26ebda 100644
--- a/tests/annotation/multi/src/main/java/demo/Application.java
+++ b/tests/annotation/multi/src/main/java/demo/Application.java
@@ -6,6 +6,7 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.security.oauth2.OAuth2AutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
@@ -21,7 +22,8 @@
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
-@SpringBootApplication
+// TODO: remove the exclusion when Spring Boot 1.5.2 is out
+@SpringBootApplication(exclude=OAuth2AutoConfiguration.class)
@RestController
public class Application {
diff --git a/tests/annotation/multi/src/test/java/demo/ApplicationTests.java b/tests/annotation/multi/src/test/java/demo/ApplicationTests.java
index 15eca8da6..34f49b849 100644
--- a/tests/annotation/multi/src/test/java/demo/ApplicationTests.java
+++ b/tests/annotation/multi/src/test/java/demo/ApplicationTests.java
@@ -2,15 +2,11 @@
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.springframework.boot.test.IntegrationTest;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import org.springframework.test.context.web.WebAppConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
-@RunWith(SpringJUnit4ClassRunner.class)
-@SpringApplicationConfiguration(classes = Application.class)
-@WebAppConfiguration
-@IntegrationTest("server.port=0")
+@RunWith(SpringRunner.class)
+@SpringBootTest
public class ApplicationTests {
@Test
diff --git a/tests/annotation/multi/src/test/java/demo/AuthorizationCodeProviderTests.java b/tests/annotation/multi/src/test/java/demo/AuthorizationCodeProviderTests.java
index 632098bf1..2ef50fde6 100755
--- a/tests/annotation/multi/src/test/java/demo/AuthorizationCodeProviderTests.java
+++ b/tests/annotation/multi/src/test/java/demo/AuthorizationCodeProviderTests.java
@@ -12,14 +12,11 @@
*/
package demo;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-
import sparklr.common.AbstractAuthorizationCodeProviderTests;
/**
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes = Application.class)
public class AuthorizationCodeProviderTests extends AbstractAuthorizationCodeProviderTests {
}
diff --git a/tests/annotation/multi/src/test/java/demo/ClientCredentialsProviderTests.java b/tests/annotation/multi/src/test/java/demo/ClientCredentialsProviderTests.java
index af8190074..857ff7fa0 100644
--- a/tests/annotation/multi/src/test/java/demo/ClientCredentialsProviderTests.java
+++ b/tests/annotation/multi/src/test/java/demo/ClientCredentialsProviderTests.java
@@ -1,13 +1,10 @@
package demo;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-
import sparklr.common.AbstractClientCredentialsProviderTests;
/**
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes=Application.class)
public class ClientCredentialsProviderTests extends AbstractClientCredentialsProviderTests {
diff --git a/tests/annotation/multi/src/test/java/demo/ImplicitProviderTests.java b/tests/annotation/multi/src/test/java/demo/ImplicitProviderTests.java
index 7a8958187..0e34ccc7d 100644
--- a/tests/annotation/multi/src/test/java/demo/ImplicitProviderTests.java
+++ b/tests/annotation/multi/src/test/java/demo/ImplicitProviderTests.java
@@ -1,13 +1,10 @@
package demo;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-
import sparklr.common.AbstractImplicitProviderTests;
/**
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes=Application.class)
public class ImplicitProviderTests extends AbstractImplicitProviderTests {
}
diff --git a/tests/annotation/multi/src/test/java/demo/ProtectedResourceTests.java b/tests/annotation/multi/src/test/java/demo/ProtectedResourceTests.java
index aa30f20f6..bf1dfd35f 100644
--- a/tests/annotation/multi/src/test/java/demo/ProtectedResourceTests.java
+++ b/tests/annotation/multi/src/test/java/demo/ProtectedResourceTests.java
@@ -17,7 +17,6 @@
import static org.junit.Assert.assertTrue;
import org.junit.Test;
-import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
@@ -27,7 +26,6 @@
* @author Dave Syer
*
*/
-@SpringApplicationConfiguration(classes = Application.class)
public class ProtectedResourceTests extends AbstractProtectedResourceTests {
@Test
diff --git a/tests/annotation/multi/src/test/java/demo/RefreshTokenSupportTests.java b/tests/annotation/multi/src/test/java/demo/RefreshTokenSupportTests.java
index 4ed370eea..417bac867 100644
--- a/tests/annotation/multi/src/test/java/demo/RefreshTokenSupportTests.java
+++ b/tests/annotation/multi/src/test/java/demo/RefreshTokenSupportTests.java
@@ -1,13 +1,10 @@
package demo;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-
import sparklr.common.AbstractRefreshTokenSupportTests;
/**
* @author Ryan Heaton
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes=Application.class)
public class RefreshTokenSupportTests extends AbstractRefreshTokenSupportTests {
}
diff --git a/tests/annotation/multi/src/test/java/demo/ResourceOwnerPasswordProviderTests.java b/tests/annotation/multi/src/test/java/demo/ResourceOwnerPasswordProviderTests.java
index 886c48e28..8a82b64dd 100644
--- a/tests/annotation/multi/src/test/java/demo/ResourceOwnerPasswordProviderTests.java
+++ b/tests/annotation/multi/src/test/java/demo/ResourceOwnerPasswordProviderTests.java
@@ -5,7 +5,6 @@
import java.util.Arrays;
import org.junit.Test;
-import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.http.HttpStatus;
import org.springframework.security.oauth2.client.test.OAuth2ContextConfiguration;
@@ -14,7 +13,6 @@
/**
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes=Application.class)
public class ResourceOwnerPasswordProviderTests extends AbstractResourceOwnerPasswordProviderTests {
@Test
diff --git a/tests/annotation/pom.xml b/tests/annotation/pom.xml
index 411d5a2bf..065a54434 100644
--- a/tests/annotation/pom.xml
+++ b/tests/annotation/pom.xml
@@ -4,7 +4,7 @@
org.demo
spring-oauth2-tests-parent
- 2.0.13.BUILD-SNAPSHOT
+ 2.1.1.BUILD-SNAPSHOT
pom
@@ -30,7 +30,7 @@
org.springframework.boot
spring-boot-starter-parent
- 1.3.5.RELEASE
+ 1.5.1.RELEASE
@@ -39,7 +39,7 @@
org.springframework.security.oauth
spring-security-oauth2
- 2.0.13.BUILD-SNAPSHOT
+ 2.1.1.BUILD-SNAPSHOT
jackson-mapper-asl
@@ -50,7 +50,7 @@
org.springframework.security
spring-security-jwt
- 1.0.3.RELEASE
+ 1.0.7.RELEASE
diff --git a/tests/annotation/resource/pom.xml b/tests/annotation/resource/pom.xml
index 6d3b500f1..df34736a2 100644
--- a/tests/annotation/resource/pom.xml
+++ b/tests/annotation/resource/pom.xml
@@ -10,7 +10,7 @@
org.demo
spring-oauth2-tests-parent
- 2.0.13.BUILD-SNAPSHOT
+ 2.1.1.BUILD-SNAPSHOT
diff --git a/tests/annotation/resource/src/main/java/demo/Application.java b/tests/annotation/resource/src/main/java/demo/Application.java
index 2758734b1..55498e567 100644
--- a/tests/annotation/resource/src/main/java/demo/Application.java
+++ b/tests/annotation/resource/src/main/java/demo/Application.java
@@ -1,19 +1,15 @@
package demo;
import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.ComponentScan;
-import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
-@Configuration
-@ComponentScan
-@EnableAutoConfiguration
+@SpringBootApplication
@EnableResourceServer
@RestController
public class Application {
diff --git a/tests/annotation/resource/src/main/resources/application.yml b/tests/annotation/resource/src/main/resources/application.yml
index a9c0149f0..c88891b00 100644
--- a/tests/annotation/resource/src/main/resources/application.yml
+++ b/tests/annotation/resource/src/main/resources/application.yml
@@ -6,3 +6,6 @@ management:
security:
user:
password: password
+ oauth2:
+ resource:
+ filter-order: 3
diff --git a/tests/annotation/resource/src/test/java/demo/ApplicationTests.java b/tests/annotation/resource/src/test/java/demo/ApplicationTests.java
index 15eca8da6..34f49b849 100644
--- a/tests/annotation/resource/src/test/java/demo/ApplicationTests.java
+++ b/tests/annotation/resource/src/test/java/demo/ApplicationTests.java
@@ -2,15 +2,11 @@
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.springframework.boot.test.IntegrationTest;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import org.springframework.test.context.web.WebAppConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
-@RunWith(SpringJUnit4ClassRunner.class)
-@SpringApplicationConfiguration(classes = Application.class)
-@WebAppConfiguration
-@IntegrationTest("server.port=0")
+@RunWith(SpringRunner.class)
+@SpringBootTest
public class ApplicationTests {
@Test
diff --git a/tests/annotation/resource/src/test/java/demo/ProtectedResourceTests.java b/tests/annotation/resource/src/test/java/demo/ProtectedResourceTests.java
index c752cbe12..302b30f96 100644
--- a/tests/annotation/resource/src/test/java/demo/ProtectedResourceTests.java
+++ b/tests/annotation/resource/src/test/java/demo/ProtectedResourceTests.java
@@ -13,15 +13,12 @@
package demo;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-
import sparklr.common.AbstractProtectedResourceTests;
/**
* @author Dave Syer
*
*/
-@SpringApplicationConfiguration(classes = Application.class)
public class ProtectedResourceTests extends AbstractProtectedResourceTests {
}
diff --git a/tests/annotation/ssl/pom.xml b/tests/annotation/ssl/pom.xml
index 13dbe9cd3..9a6a8a01a 100644
--- a/tests/annotation/ssl/pom.xml
+++ b/tests/annotation/ssl/pom.xml
@@ -11,7 +11,7 @@
org.demo
spring-oauth2-tests-parent
- 2.0.13.BUILD-SNAPSHOT
+ 2.1.1.BUILD-SNAPSHOT
diff --git a/tests/annotation/vanilla/pom.xml b/tests/annotation/vanilla/pom.xml
index 590597180..7b31b952a 100644
--- a/tests/annotation/vanilla/pom.xml
+++ b/tests/annotation/vanilla/pom.xml
@@ -10,7 +10,7 @@
org.demo
spring-oauth2-tests-parent
- 2.0.13.BUILD-SNAPSHOT
+ 2.1.1.BUILD-SNAPSHOT
diff --git a/tests/annotation/vanilla/src/main/resources/application.yml b/tests/annotation/vanilla/src/main/resources/application.yml
index 5414a20b3..21a0bac83 100644
--- a/tests/annotation/vanilla/src/main/resources/application.yml
+++ b/tests/annotation/vanilla/src/main/resources/application.yml
@@ -6,6 +6,9 @@ management:
security:
user:
password: password
+ oauth2:
+ resource:
+ filter-order: 3
logging:
level:
org.springframework.security: WARN
\ No newline at end of file
diff --git a/tests/annotation/vanilla/src/test/java/demo/ApplicationTests.java b/tests/annotation/vanilla/src/test/java/demo/ApplicationTests.java
index 15eca8da6..6a1f865e8 100644
--- a/tests/annotation/vanilla/src/test/java/demo/ApplicationTests.java
+++ b/tests/annotation/vanilla/src/test/java/demo/ApplicationTests.java
@@ -2,15 +2,12 @@
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.springframework.boot.test.IntegrationTest;
-import org.springframework.boot.test.SpringApplicationConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import org.springframework.test.context.web.WebAppConfiguration;
@RunWith(SpringJUnit4ClassRunner.class)
-@SpringApplicationConfiguration(classes = Application.class)
-@WebAppConfiguration
-@IntegrationTest("server.port=0")
+@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)
public class ApplicationTests {
@Test
diff --git a/tests/annotation/vanilla/src/test/java/demo/AuthorizationCodeProviderCookieTests.java b/tests/annotation/vanilla/src/test/java/demo/AuthorizationCodeProviderCookieTests.java
index 7b614e004..e9083e3f3 100644
--- a/tests/annotation/vanilla/src/test/java/demo/AuthorizationCodeProviderCookieTests.java
+++ b/tests/annotation/vanilla/src/test/java/demo/AuthorizationCodeProviderCookieTests.java
@@ -16,7 +16,6 @@
import static org.junit.Assert.assertNotNull;
import org.junit.Test;
-import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.security.oauth2.client.test.OAuth2ContextConfiguration;
@@ -27,7 +26,6 @@
/**
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes = Application.class)
public class AuthorizationCodeProviderCookieTests extends AbstractEmptyAuthorizationCodeProviderTests {
@Test
diff --git a/tests/annotation/vanilla/src/test/java/demo/AuthorizationCodeProviderTests.java b/tests/annotation/vanilla/src/test/java/demo/AuthorizationCodeProviderTests.java
index 49a38d4ab..34cdef81b 100755
--- a/tests/annotation/vanilla/src/test/java/demo/AuthorizationCodeProviderTests.java
+++ b/tests/annotation/vanilla/src/test/java/demo/AuthorizationCodeProviderTests.java
@@ -17,7 +17,6 @@
import static org.junit.Assert.assertTrue;
import org.junit.Test;
-import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.oauth2.client.test.OAuth2ContextConfiguration;
@@ -28,7 +27,6 @@
/**
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes = Application.class)
public class AuthorizationCodeProviderTests extends AbstractAuthorizationCodeProviderTests {
@Test
diff --git a/tests/annotation/vanilla/src/test/java/demo/ClientCredentialsProviderTests.java b/tests/annotation/vanilla/src/test/java/demo/ClientCredentialsProviderTests.java
index af8190074..857ff7fa0 100644
--- a/tests/annotation/vanilla/src/test/java/demo/ClientCredentialsProviderTests.java
+++ b/tests/annotation/vanilla/src/test/java/demo/ClientCredentialsProviderTests.java
@@ -1,13 +1,10 @@
package demo;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-
import sparklr.common.AbstractClientCredentialsProviderTests;
/**
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes=Application.class)
public class ClientCredentialsProviderTests extends AbstractClientCredentialsProviderTests {
diff --git a/tests/annotation/vanilla/src/test/java/demo/GlobalMethodSecurityTests.java b/tests/annotation/vanilla/src/test/java/demo/GlobalMethodSecurityTests.java
index 5977d393d..fcbf10952 100644
--- a/tests/annotation/vanilla/src/test/java/demo/GlobalMethodSecurityTests.java
+++ b/tests/annotation/vanilla/src/test/java/demo/GlobalMethodSecurityTests.java
@@ -1,23 +1,23 @@
package demo;
-import org.springframework.boot.test.SpringApplicationConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration;
import org.springframework.security.oauth2.provider.expression.OAuth2MethodSecurityExpressionHandler;
-import sparklr.common.AbstractProtectedResourceTests;
import demo.GlobalMethodSecurityTests.GlobalSecurityConfiguration;
+import sparklr.common.AbstractProtectedResourceTests;
-@SpringApplicationConfiguration(classes = { Application.class,
- GlobalSecurityConfiguration.class })
+@SpringBootTest(classes = { Application.class, GlobalSecurityConfiguration.class }, webEnvironment=WebEnvironment.RANDOM_PORT)
public class GlobalMethodSecurityTests extends AbstractProtectedResourceTests {
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
- protected static class GlobalSecurityConfiguration extends
- GlobalMethodSecurityConfiguration {
+ protected static class GlobalSecurityConfiguration
+ extends GlobalMethodSecurityConfiguration {
@Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
diff --git a/tests/annotation/vanilla/src/test/java/demo/ImplicitProviderTests.java b/tests/annotation/vanilla/src/test/java/demo/ImplicitProviderTests.java
index 06ebe766b..ef7c254ce 100644
--- a/tests/annotation/vanilla/src/test/java/demo/ImplicitProviderTests.java
+++ b/tests/annotation/vanilla/src/test/java/demo/ImplicitProviderTests.java
@@ -14,8 +14,7 @@
import org.junit.BeforeClass;
import org.junit.Test;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-import org.springframework.boot.test.TestRestTemplate;
+import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.oauth2.client.test.OAuth2ContextConfiguration;
@@ -26,7 +25,6 @@
/**
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes = Application.class)
public class ImplicitProviderTests extends AbstractImplicitProviderTests {
@BeforeClass
diff --git a/tests/annotation/vanilla/src/test/java/demo/ProtectedResourceTests.java b/tests/annotation/vanilla/src/test/java/demo/ProtectedResourceTests.java
index c752cbe12..302b30f96 100644
--- a/tests/annotation/vanilla/src/test/java/demo/ProtectedResourceTests.java
+++ b/tests/annotation/vanilla/src/test/java/demo/ProtectedResourceTests.java
@@ -13,15 +13,12 @@
package demo;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-
import sparklr.common.AbstractProtectedResourceTests;
/**
* @author Dave Syer
*
*/
-@SpringApplicationConfiguration(classes = Application.class)
public class ProtectedResourceTests extends AbstractProtectedResourceTests {
}
diff --git a/tests/annotation/vanilla/src/test/java/demo/RefreshTokenSupportTests.java b/tests/annotation/vanilla/src/test/java/demo/RefreshTokenSupportTests.java
index 4ed370eea..417bac867 100644
--- a/tests/annotation/vanilla/src/test/java/demo/RefreshTokenSupportTests.java
+++ b/tests/annotation/vanilla/src/test/java/demo/RefreshTokenSupportTests.java
@@ -1,13 +1,10 @@
package demo;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-
import sparklr.common.AbstractRefreshTokenSupportTests;
/**
* @author Ryan Heaton
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes=Application.class)
public class RefreshTokenSupportTests extends AbstractRefreshTokenSupportTests {
}
diff --git a/tests/annotation/vanilla/src/test/java/demo/ResourceOwnerPasswordProviderTests.java b/tests/annotation/vanilla/src/test/java/demo/ResourceOwnerPasswordProviderTests.java
index 28a8e9f84..31a0f75b8 100644
--- a/tests/annotation/vanilla/src/test/java/demo/ResourceOwnerPasswordProviderTests.java
+++ b/tests/annotation/vanilla/src/test/java/demo/ResourceOwnerPasswordProviderTests.java
@@ -3,8 +3,7 @@
import static org.junit.Assert.assertEquals;
import org.junit.Test;
-import org.springframework.boot.test.SpringApplicationConfiguration;
-import org.springframework.boot.test.TestRestTemplate;
+import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.oauth2.client.test.OAuth2ContextConfiguration;
@@ -14,7 +13,6 @@
/**
* @author Dave Syer
*/
-@SpringApplicationConfiguration(classes=Application.class)
public class ResourceOwnerPasswordProviderTests extends AbstractResourceOwnerPasswordProviderTests {
@Test
diff --git a/tests/pom.xml b/tests/pom.xml
index 4d58bbcb0..234e3141c 100644
--- a/tests/pom.xml
+++ b/tests/pom.xml
@@ -4,7 +4,7 @@
org.springframework.security.oauth
spring-security-oauth-parent
- 2.0.13.BUILD-SNAPSHOT
+ 2.1.1.BUILD-SNAPSHOT
spring-security-oauth-tests
diff --git a/tests/xml/approval/pom.xml b/tests/xml/approval/pom.xml
index f66b6a0f6..c8569a5d2 100644
--- a/tests/xml/approval/pom.xml
+++ b/tests/xml/approval/pom.xml
@@ -10,7 +10,7 @@
org.demo
spring-oauth2-tests-xml-parent
- 2.0.13.BUILD-SNAPSHOT
+ 2.1.1.BUILD-SNAPSHOT
diff --git a/tests/xml/client/pom.xml b/tests/xml/client/pom.xml
index 349d602a2..049f30793 100644
--- a/tests/xml/client/pom.xml
+++ b/tests/xml/client/pom.xml
@@ -10,7 +10,7 @@
org.demo
spring-oauth2-tests-xml-parent
- 2.0.13.BUILD-SNAPSHOT
+ 2.1.1.BUILD-SNAPSHOT
diff --git a/tests/xml/common/pom.xml b/tests/xml/common/pom.xml
index 654689b20..4d15848f3 100644
--- a/tests/xml/common/pom.xml
+++ b/tests/xml/common/pom.xml
@@ -10,7 +10,7 @@
org.demo
spring-oauth2-tests-xml-parent
- 2.0.13.BUILD-SNAPSHOT
+ 2.1.1.BUILD-SNAPSHOT
diff --git a/tests/xml/form/pom.xml b/tests/xml/form/pom.xml
index e6302c055..37d5a50f7 100644
--- a/tests/xml/form/pom.xml
+++ b/tests/xml/form/pom.xml
@@ -10,7 +10,7 @@
org.demo
spring-oauth2-tests-xml-parent
- 2.0.13.BUILD-SNAPSHOT
+ 2.1.1.BUILD-SNAPSHOT
diff --git a/tests/xml/jdbc/pom.xml b/tests/xml/jdbc/pom.xml
index e777afb3d..1c130362a 100644
--- a/tests/xml/jdbc/pom.xml
+++ b/tests/xml/jdbc/pom.xml
@@ -10,7 +10,7 @@
org.demo
spring-oauth2-tests-xml-parent
- 2.0.13.BUILD-SNAPSHOT
+ 2.1.1.BUILD-SNAPSHOT
diff --git a/tests/xml/jwt/pom.xml b/tests/xml/jwt/pom.xml
index 965689999..0275e803f 100644
--- a/tests/xml/jwt/pom.xml
+++ b/tests/xml/jwt/pom.xml
@@ -10,7 +10,7 @@
org.demo
spring-oauth2-tests-xml-parent
- 2.0.13.BUILD-SNAPSHOT
+ 2.1.1.BUILD-SNAPSHOT
diff --git a/tests/xml/mappings/pom.xml b/tests/xml/mappings/pom.xml
index 84d9a32d9..f55d557c9 100644
--- a/tests/xml/mappings/pom.xml
+++ b/tests/xml/mappings/pom.xml
@@ -10,7 +10,7 @@
org.demo
spring-oauth2-tests-xml-parent
- 2.0.13.BUILD-SNAPSHOT
+ 2.1.1.BUILD-SNAPSHOT
diff --git a/tests/xml/pom.xml b/tests/xml/pom.xml
index 421c0c48a..887dca74e 100644
--- a/tests/xml/pom.xml
+++ b/tests/xml/pom.xml
@@ -4,7 +4,7 @@
org.demo
spring-oauth2-tests-xml-parent
- 2.0.13.BUILD-SNAPSHOT
+ 2.1.1.BUILD-SNAPSHOT
pom
@@ -33,7 +33,7 @@
org.springframework.security.oauth
spring-security-oauth2
- 2.0.13.BUILD-SNAPSHOT
+ 2.1.1.BUILD-SNAPSHOT
jackson-mapper-asl
diff --git a/tests/xml/vanilla/pom.xml b/tests/xml/vanilla/pom.xml
index f64a2d1f2..abe8c9fa1 100644
--- a/tests/xml/vanilla/pom.xml
+++ b/tests/xml/vanilla/pom.xml
@@ -10,7 +10,7 @@
org.demo
spring-oauth2-tests-xml-parent
- 2.0.13.BUILD-SNAPSHOT
+ 2.1.1.BUILD-SNAPSHOT